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.

2850 lines
84 KiB

  1. // Shell.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. extern "C"
  9. {
  10. #include <nt.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. #include <ntlsa.h>
  14. #include <ntsam.h>
  15. }
  16. #include <cmnhdr.h>
  17. #include <Windows.h>
  18. #include <LmAccess.h>
  19. #include <LmApiBuf.h>
  20. #include <LmErr.h>
  21. #include <LmWkSta.h>
  22. #include <WinBase.h>
  23. #include <IpTypes.h>
  24. #include <shfolder.h>
  25. #include <Debug.h>
  26. #include <MsgFile.h>
  27. #include <TlntUtils.h>
  28. #include <Shell.h>
  29. #include <LibFuncs.h>
  30. #include <KillApps.h>
  31. #include <Session.h>
  32. #include <Telnetd.h>
  33. #include <wincrypt.h>
  34. #include <sddl.h>
  35. #pragma warning(disable:4706)
  36. #pragma warning(disable: 4127)
  37. using namespace _Utils;
  38. using CDebugLevel::TRACE_DEBUGGING;
  39. using CDebugLevel::TRACE_HANDLE;
  40. using CDebugLevel::TRACE_SOCKET;
  41. extern HANDLE g_hSyncCloseHandle;
  42. extern HCRYPTPROV g_hProv;
  43. LPWSTR wideHomeDir = NULL;
  44. BOOL create_desktop_for_this_session(
  45. HANDLE client_token,
  46. LPTSTR *desktop_name
  47. )
  48. {
  49. #define NO_OF_SIDS 4
  50. BOOL success = FALSE;
  51. DWORD win32error = NO_ERROR;
  52. PSID administrators_sid = NULL,
  53. client_sid = NULL,
  54. local_system_sid = NULL,
  55. network_service_sid = NULL,
  56. local_service_sid = NULL;
  57. PACL new_acl = NULL;
  58. SECURITY_DESCRIPTOR sd = { 0 };
  59. SECURITY_INFORMATION sec_i = DACL_SECURITY_INFORMATION;
  60. BYTE client_sid_buffer[256] = { 0 };
  61. HDESK desktop = NULL;
  62. /*
  63. We are going to set the following entries for the Desktop
  64. 1. System Full Control
  65. 2. Administrators FullControl
  66. 3. client FullControl
  67. 4. Localservice full control
  68. //5. Network service full control
  69. */
  70. {
  71. SID_IDENTIFIER_AUTHORITY local_system_authority = SECURITY_NT_AUTHORITY;
  72. if (! AllocateAndInitializeSid(
  73. &local_system_authority,
  74. 2, /* there are only two sub-authorities */
  75. SECURITY_BUILTIN_DOMAIN_RID,
  76. DOMAIN_ALIAS_RID_ADMINS,
  77. 0,0,0,0,0,0, /* Don't care about the rest */
  78. &administrators_sid
  79. ))
  80. {
  81. goto CLEANUP_AND_GET_OUT;
  82. }
  83. if (! AllocateAndInitializeSid(
  84. &local_system_authority,
  85. 1, /* there is only two sub-authority */
  86. SECURITY_LOCAL_SYSTEM_RID,
  87. 0,0,0,0,0,0,0, /* Don't care about the rest */
  88. &local_system_sid
  89. ))
  90. {
  91. goto CLEANUP_AND_GET_OUT;
  92. }
  93. #ifndef SECURITY_LOCAL_SERVICE_RID
  94. #define SECURITY_LOCAL_SERVICE_RID (0x00000013L)
  95. //#define SECURITY_NETWORK_SERVICE_RID (0x00000014L)
  96. #endif
  97. //Build LocalLocal sid
  98. if ( ! AllocateAndInitializeSid(
  99. &local_system_authority,
  100. 1, /* there is only two sub-authority */
  101. SECURITY_LOCAL_SERVICE_RID,
  102. 0,0,0,0,0,0,0, /* Don't care about the rest */
  103. &local_service_sid
  104. ) )
  105. {
  106. goto CLEANUP_AND_GET_OUT;
  107. }
  108. /*
  109. //Build LocalSystem sid
  110. if ( ! AllocateAndInitializeSid(
  111. &local_system_authority,
  112. 1, /* there is only two sub-authority /
  113. SECURITY_NETWORK_SERVICE_RID,
  114. 0,0,0,0,0,0,0, /* Don't care about the rest /
  115. &network_service_sid
  116. ) )
  117. {
  118. goto CLEANUP_AND_GET_OUT;
  119. }
  120. */
  121. }
  122. {
  123. DWORD required = 0;
  124. if (! GetTokenInformation(
  125. client_token,
  126. TokenUser,
  127. (LPVOID)client_sid_buffer,
  128. sizeof(client_sid_buffer),
  129. &required
  130. ))
  131. {
  132. goto CLEANUP_AND_GET_OUT;
  133. }
  134. client_sid = ((TOKEN_USER *)client_sid_buffer)->User.Sid;
  135. }
  136. {
  137. DWORD aclSize;
  138. // Add Identical settings both for desktop and for windowstation
  139. aclSize = sizeof(ACL) +
  140. (NO_OF_SIDS * sizeof(ACCESS_ALLOWED_ACE)) +
  141. GetLengthSid(administrators_sid) +
  142. GetLengthSid(client_sid)+
  143. GetLengthSid(local_system_sid) +
  144. GetLengthSid(local_service_sid) -
  145. //GetLengthSid(network_service_sid) -
  146. (NO_OF_SIDS * sizeof(DWORD));
  147. new_acl = (PACL) new BYTE[aclSize];
  148. if (NULL == new_acl)
  149. {
  150. goto CLEANUP_AND_GET_OUT;
  151. }
  152. if (!InitializeAcl(new_acl, aclSize, ACL_REVISION))
  153. {
  154. goto CLEANUP_AND_GET_OUT;
  155. }
  156. }
  157. if (!AddAccessAllowedAce(
  158. new_acl,
  159. ACL_REVISION,
  160. GENERIC_ALL,
  161. local_system_sid
  162. ))
  163. {
  164. goto CLEANUP_AND_GET_OUT;
  165. }
  166. if (!AddAccessAllowedAce(
  167. new_acl,
  168. ACL_REVISION,
  169. GENERIC_ALL,
  170. administrators_sid
  171. ))
  172. {
  173. goto CLEANUP_AND_GET_OUT;
  174. }
  175. if (!AddAccessAllowedAce(
  176. new_acl,
  177. ACL_REVISION,
  178. GENERIC_ALL,
  179. client_sid
  180. ))
  181. {
  182. goto CLEANUP_AND_GET_OUT;
  183. }
  184. if(!AddAccessAllowedAce(
  185. new_acl,
  186. ACL_REVISION,
  187. GENERIC_ALL,
  188. local_service_sid
  189. ))
  190. {
  191. goto CLEANUP_AND_GET_OUT;
  192. }
  193. /*
  194. if(!AddAccessAllowedAce(
  195. new_acl,
  196. ACL_REVISION,
  197. GENERIC_ALL,
  198. network_service_sid
  199. ))
  200. {
  201. goto CLEANUP_AND_GET_OUT;
  202. }
  203. */
  204. if ( !InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION ) )
  205. {
  206. goto CLEANUP_AND_GET_OUT;
  207. }
  208. if ( !SetSecurityDescriptorDacl(&sd, TRUE, new_acl, FALSE) )
  209. {
  210. goto CLEANUP_AND_GET_OUT;
  211. }
  212. {
  213. SECURITY_ATTRIBUTES sa = { 0 };
  214. if(!ConvertSidToStringSid(client_sid,&(*desktop_name)))
  215. {
  216. *desktop_name = NULL;
  217. goto CLEANUP_AND_GET_OUT;
  218. }
  219. sa.nLength = sizeof(sa);
  220. sa.lpSecurityDescriptor = &sd;
  221. desktop = CreateDesktop(
  222. *desktop_name,
  223. NULL,
  224. NULL,
  225. 0,
  226. MAXIMUM_ALLOWED,
  227. &sa);
  228. if (NULL == desktop)
  229. {
  230. goto CLEANUP_AND_GET_OUT;
  231. }
  232. SetThreadDesktop(desktop);
  233. CloseDesktop(desktop);
  234. success = TRUE;
  235. }
  236. CLEANUP_AND_GET_OUT:
  237. if (! success)
  238. {
  239. win32error = GetLastError();
  240. _TRACE(TRACE_DEBUGGING,L"Creation and setting of windowstation/desktop failed with %d",win32error);
  241. LogFormattedGetLastError(EVENTLOG_ERROR_TYPE, TELNET_MSG_ERROR_CREATE_DESKTOP_FAILURE, win32error);
  242. if(*desktop_name)
  243. {
  244. LocalFree(*desktop_name);
  245. *desktop_name = NULL;
  246. }
  247. if(desktop)
  248. {
  249. CloseDesktop(desktop);
  250. }
  251. }
  252. if ( administrators_sid != NULL )
  253. {
  254. FreeSid (administrators_sid );
  255. }
  256. if ( local_system_sid!= NULL )
  257. {
  258. FreeSid (local_system_sid);
  259. }
  260. if( local_service_sid != NULL )
  261. {
  262. FreeSid (local_service_sid);
  263. }
  264. /*
  265. if( network_service_sid != NULL )
  266. {
  267. FreeSid (network_service_sid );
  268. }
  269. */
  270. if (new_acl)
  271. delete [] new_acl;
  272. return( success );
  273. #undef NO_OF_SIDS
  274. }
  275. VOID CleanupClientToken(
  276. HANDLE token
  277. )
  278. {
  279. TOKEN_PRIVILEGES *tp = NULL;
  280. DWORD needed_length = 0;
  281. // DbgUserBreakPoint();
  282. // Currently, we find that all the privileges enabled in the token obtained via ntlm logon so
  283. // Disable everything except SeChangeNotifyPrivilege
  284. if (GetTokenInformation(
  285. token,
  286. TokenPrivileges,
  287. NULL,
  288. 0,
  289. &needed_length
  290. ))
  291. {
  292. // No way this can be a success, so just return
  293. DbgPrint("TLNTSESS: How did GetTokenInformation succeed?\n");
  294. return;
  295. }
  296. tp = (TOKEN_PRIVILEGES *)GlobalAlloc(GPTR, needed_length);
  297. if (tp)
  298. {
  299. if (GetTokenInformation(
  300. token,
  301. TokenPrivileges,
  302. tp,
  303. needed_length,
  304. &needed_length
  305. ))
  306. {
  307. DWORD x;
  308. LUID change_notify = RtlConvertUlongToLuid(SE_CHANGE_NOTIFY_PRIVILEGE);
  309. for (x = 0; x < tp->PrivilegeCount; x ++)
  310. {
  311. if ((! RtlEqualLuid(&(tp->Privileges[x].Luid), &change_notify)) &&
  312. (tp->Privileges[x].Attributes & SE_PRIVILEGE_ENABLED)
  313. )
  314. {
  315. tp->Privileges[x].Attributes &= ~(SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED);
  316. }
  317. }
  318. if (! AdjustTokenPrivileges(
  319. token,
  320. FALSE, // Don't disable all
  321. tp,
  322. needed_length,
  323. NULL, // Don't need the prior state & length
  324. NULL
  325. ))
  326. {
  327. DbgPrint("TLNTSESS: AdjustTokenPrivileges failed with %u\n", GetLastError());
  328. }
  329. }
  330. else
  331. {
  332. DbgPrint("TLNTSESS: GetTokInfo failed with %u\n", GetLastError());
  333. }
  334. GlobalFree(tp);
  335. }
  336. }
  337. CShell::CShell()
  338. {
  339. m_pSession = NULL;
  340. m_bIsLocalHost = false;
  341. m_hCurrUserKey = NULL;
  342. m_lpEnv = NULL;
  343. m_hProcess = NULL;
  344. m_hTempProcess = NULL;
  345. hUserEnvLib = NULL;
  346. pHomeDir = NULL;
  347. pHomeDrive = NULL;
  348. pLogonScriptPath = NULL;
  349. pProfilePath = NULL;
  350. pServerName = NULL;
  351. m_pwszAppDataDir = NULL;
  352. m_pucDataFromCmd = NULL;
  353. m_dwDataSizeFromCmd =0;
  354. m_hReadFromCmd = NULL;
  355. m_hWriteByCmd = NULL;
  356. }
  357. void
  358. CShell::FreeInitialVariables()
  359. {
  360. delete[] pHomeDir;
  361. delete[] pHomeDrive;
  362. delete[] pLogonScriptPath;
  363. delete[] pProfilePath;
  364. delete[] pServerName;
  365. delete[] m_pwszAppDataDir;
  366. pHomeDir = NULL;
  367. pHomeDrive = NULL;
  368. pLogonScriptPath = NULL;
  369. pProfilePath = NULL;
  370. pServerName = NULL;
  371. m_pwszAppDataDir = NULL;
  372. }
  373. CShell::~CShell()
  374. {
  375. if( m_pSession->m_bNtVersionGTE5 )
  376. {
  377. //Free libraries
  378. FreeLibrary( hUserEnvLib );
  379. }
  380. FreeInitialVariables();
  381. if( m_pSession->CSession::m_bIsStreamMode )
  382. {
  383. delete[] m_pucDataFromCmd;
  384. TELNET_CLOSE_HANDLE( m_oReadFromCmd.hEvent );
  385. TELNET_CLOSE_HANDLE( m_hReadFromCmd );
  386. TELNET_CLOSE_HANDLE( m_hWriteByCmd );
  387. }
  388. }
  389. void
  390. CShell::Init ( CSession *pSession )
  391. {
  392. _chASSERT( pSession != 0 );
  393. m_pSession = pSession;
  394. }
  395. bool
  396. CShell::StartUserSession ( )
  397. {
  398. LoadLibNGetProc( );
  399. LoadTheProfile();
  400. //
  401. // If Japanese NT then we need to set the console fonts to TrueType
  402. //
  403. DWORD dwCodePage = GetACP();
  404. if(dwCodePage == 932||dwCodePage == 936||dwCodePage == 949||dwCodePage == 950)
  405. {
  406. DoFESpecificProcessing();
  407. }
  408. if( !StartProcess( ) )
  409. {
  410. return ( FALSE );
  411. }
  412. m_pSession->AddHandleToWaitOn( m_hProcess );
  413. if( m_pSession->CSession::m_bIsStreamMode )
  414. {
  415. m_pSession->CSession::AddHandleToWaitOn( m_oReadFromCmd.hEvent );
  416. if( !IssueReadFromCmd() )
  417. {
  418. return( FALSE );
  419. }
  420. }
  421. //Start the scraper
  422. if( !m_pSession->CScraper::InitSession() )
  423. {
  424. return ( FALSE );
  425. }
  426. return ( TRUE );
  427. }
  428. bool
  429. CShell::CreateIOHandles()
  430. {
  431. BOOL dwStatus = 0;
  432. _chVERIFY2( dwStatus = FreeConsole() );
  433. if( !dwStatus )
  434. {
  435. LogFormattedGetLastError( EVENTLOG_ERROR_TYPE, 0, GetLastError() );
  436. }
  437. _chVERIFY2( dwStatus = AllocConsole() );
  438. if( !dwStatus )
  439. {
  440. LogFormattedGetLastError( EVENTLOG_ERROR_TYPE, 0, GetLastError() );
  441. }
  442. //Fix for HANDLE LEAK
  443. TELNET_CLOSE_HANDLE(m_pSession->CScraper::m_hConBufIn);
  444. TELNET_CLOSE_HANDLE(m_pSession->CScraper::m_hConBufOut);
  445. SECURITY_ATTRIBUTES sa;
  446. INHERITABLE_NULL_DESCRIPTOR_ATTRIBUTE( sa );
  447. _chVERIFY2( ( m_pSession->CScraper::m_hConBufIn =
  448. CreateFileA( "CONIN$", GENERIC_READ | GENERIC_WRITE ,
  449. 0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ) ) !=
  450. INVALID_HANDLE_VALUE );
  451. if( INVALID_HANDLE_VALUE == m_pSession->CScraper::m_hConBufIn)
  452. {
  453. LogFormattedGetLastError( EVENTLOG_ERROR_TYPE, MSG_ERRCONSOLE, GetLastError() );
  454. goto ExitOnError;
  455. }
  456. _chVERIFY2( ( m_pSession->CScraper::m_hConBufOut =
  457. CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, &sa,
  458. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ) ) !=
  459. INVALID_HANDLE_VALUE );
  460. if( INVALID_HANDLE_VALUE == m_pSession->CScraper::m_hConBufOut )
  461. {
  462. LogFormattedGetLastError( EVENTLOG_ERROR_TYPE, MSG_ERRCONSOLE, GetLastError() );
  463. goto ExitOnError;
  464. }
  465. return (TRUE);
  466. ExitOnError :
  467. TELNET_CLOSE_HANDLE(m_pSession->CScraper::m_hConBufIn);
  468. TELNET_CLOSE_HANDLE(m_pSession->CScraper::m_hConBufOut);
  469. return( FALSE );
  470. }
  471. void
  472. CShell::DoFESpecificProcessing()
  473. {
  474. UCHAR InfoBuffer[ 1024 ];
  475. DWORD cbInfoBuffer = 1024;
  476. BOOL bSuccess = GetTokenInformation( m_pSession->CSession::m_hToken,
  477. TokenUser, InfoBuffer, cbInfoBuffer, &cbInfoBuffer );
  478. if(!bSuccess)
  479. {
  480. if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  481. {
  482. //
  483. // Though we need to alloc buffer and try GetTokenInformation()
  484. // again, actually it is highly unlikely; so we return false;
  485. //
  486. return;
  487. }
  488. else
  489. {
  490. _TRACE( TRACE_DEBUGGING, "Error: error getting token info");
  491. return ;
  492. }
  493. }
  494. CHAR szPathName[MAX_PATH] = { 0 };
  495. LPSTR lpszKey = NULL;
  496. DWORD dwFontSize = 0;
  497. DWORD dwFaceNameSize = 0 ;
  498. DWORD dwSize = 0;
  499. DWORD dwVal = 54;
  500. LPSTR szTextualSid = NULL; // allocated textual Sid
  501. PSID_IDENTIFIER_AUTHORITY psia;
  502. DWORD dwSubAuthorities;
  503. DWORD dwCounter;
  504. DWORD dwSidSize;
  505. DWORD dwCodePage = GetACP();
  506. LONG lRet=-1;
  507. /*++
  508. To support CHS, CHT, KOR alongwith JPN, we need to change the FaceName Value
  509. to the True Type font for that particular language.
  510. Copying the string directly into the variable doesn't work.
  511. It copies high order ASCII characters in the string instead of the DBCS characters.
  512. So we need to set the UNICODE byte values corresponding to the
  513. DBCS characters for the TT Font Names.
  514. These TT fonts are the ones which are present in Cmd.exe-Properties-Font.
  515. For US locale, the TT font is Lucida Console.
  516. But we don't need to set it on US locale. Raster Font works fine there.
  517. For FE languages, the TT fonts need to be set.
  518. --*/
  519. const TCHAR szJAPFaceName[] = { 0xFF2D ,0xFF33 ,L' ' ,0x30B4 ,0x30B7 ,0x30C3 ,0x30AF ,L'\0' };
  520. const TCHAR szCHTFaceName[] = { 0x7D30 ,0x660E ,0x9AD4 ,L'\0'};
  521. const TCHAR szKORFaceName[] = { 0xAD74 ,0xB9BC ,0xCCB4 ,L'\0'};
  522. const TCHAR szCHSFaceName[] = { 0x65B0 ,0x5B8B ,0x4F53 ,L'\0' };
  523. TCHAR szFaceNameDef[MAX_STRING_LENGTH];
  524. switch (dwCodePage)
  525. {
  526. case JAP_CODEPAGE:
  527. _tcscpy(szFaceNameDef, szJAPFaceName); //On JAP, set the FaceName to "MS Gothic"
  528. dwFontSize = JAP_FONTSIZE;
  529. break;
  530. case CHT_CODEPAGE:
  531. _tcscpy(szFaceNameDef, szCHTFaceName); //On CHT, set the FaceName to "MingLiU"
  532. dwFontSize = CHT_FONTSIZE;
  533. break;
  534. case KOR_CODEPAGE:
  535. _tcscpy(szFaceNameDef, szKORFaceName);//On KOR, set the FaceName to "GulimChe"
  536. dwFontSize = KOR_FONTSIZE;
  537. break;
  538. case CHS_CODEPAGE:
  539. _tcscpy(szFaceNameDef, szCHSFaceName);//On CHS, set the FaceName to "NSimSun"
  540. dwFontSize = CHS_FONTSIZE;
  541. break;
  542. default:
  543. _tcscpy(szFaceNameDef,L"\0");
  544. break;
  545. }
  546. dwFaceNameSize = ( _tcslen( szFaceNameDef ) + 1 ) * sizeof( TCHAR );
  547. //
  548. // Convert the SID to textual form, which is used to load
  549. // the registry hive associated with that user
  550. //
  551. //
  552. // Test if Sid is valid
  553. //
  554. if( !IsValidSid( ( ( PTOKEN_USER ) InfoBuffer )->User.Sid ) )
  555. {
  556. _TRACE( TRACE_DEBUGGING, "Error: IsValidSid()");
  557. return;
  558. }
  559. //
  560. // Get SidIdentifierAuthority
  561. //
  562. psia = GetSidIdentifierAuthority( ( ( PTOKEN_USER )InfoBuffer )->User.Sid );
  563. //
  564. // Get sidsubauthority count
  565. //
  566. dwSubAuthorities = *GetSidSubAuthorityCount( ( ( PTOKEN_USER ) InfoBuffer )->User.Sid );
  567. //
  568. // Compute buffer length
  569. // S- + SID_REVISION- + identifierauthority- + subauthorities- + NULL
  570. //
  571. dwSidSize = ( 20 + 12 + ( 12 * dwSubAuthorities ) + 1 ) * sizeof( CHAR );
  572. szTextualSid=( LPSTR ) new CHAR[dwSidSize];
  573. if( szTextualSid == NULL )
  574. {
  575. return;
  576. }
  577. //
  578. // Prepare S-SID_REVISION-
  579. //
  580. dwSidSize = sprintf( szTextualSid, "s-%lu-", SID_REVISION ); // NO Overflow, Baskar
  581. //
  582. // Prepare SidIdentifierAuthority
  583. //
  584. if( ( psia->Value[0] != 0 ) || ( psia->Value[1] != 0 ) )
  585. {
  586. dwSidSize += sprintf( szTextualSid + dwSidSize,
  587. "0x%02lx%02lx%02lx%02lx%02lx%02lx",
  588. ( USHORT )psia->Value[0],
  589. ( USHORT )psia->Value[1],
  590. ( USHORT )psia->Value[2],
  591. ( USHORT )psia->Value[3],
  592. ( USHORT )psia->Value[4],
  593. ( USHORT )psia->Value[5] ); // NO Overflow, Baskar
  594. }
  595. else
  596. {
  597. dwSidSize += sprintf( szTextualSid + dwSidSize,
  598. "%lu",
  599. ( ULONG )( psia->Value[5] ) +
  600. ( ULONG )( psia->Value[4] << 8 ) +
  601. ( ULONG )( psia->Value[3] << 16 ) +
  602. ( ULONG )( psia->Value[2] << 24 ) ); // NO Overflow, Baskar
  603. }
  604. //
  605. // Copy each SidSubAuthority
  606. //
  607. for( dwCounter = 0 ; dwCounter < dwSubAuthorities ; dwCounter++ )
  608. {
  609. dwSidSize += sprintf( szTextualSid + dwSidSize, "-%lu",
  610. *GetSidSubAuthority( ( ( PTOKEN_USER )InfoBuffer )->User.Sid, dwCounter ) ); // NO Overflow, Baskar
  611. }
  612. //
  613. // Check to see if a hive for the specified user is already loaded
  614. //
  615. HKEY hK3 = NULL;
  616. lRet = RegOpenKeyExA(
  617. HKEY_USERS,
  618. szTextualSid,
  619. 0,
  620. KEY_QUERY_VALUE,
  621. &hK3
  622. );
  623. //
  624. // ERROR_ACCESS_DENIED probably means the user hive is already loaded
  625. //
  626. if( ( lRet != ERROR_SUCCESS ) && ( lRet != ERROR_ACCESS_DENIED ) )
  627. {
  628. if( hK3 != NULL )
  629. {
  630. RegCloseKey( hK3 );
  631. }
  632. //
  633. // User hive is not loaded. Attempt to locate and load hive
  634. //
  635. LPCSTR szProfileList = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\";
  636. LPSTR szSubKey = NULL;
  637. HKEY hKey = NULL;
  638. CHAR szPath[MAX_PATH];
  639. DWORD cbPath = MAX_PATH;
  640. CHAR szExpandedPath[MAX_PATH];
  641. lRet = ERROR_SUCCESS;
  642. //
  643. // Allocate storage for ProfileList + TextualSid + NULL
  644. //
  645. szSubKey = (LPSTR) new CHAR[( strlen( szProfileList ) + strlen( szTextualSid ) + 1)];
  646. if( szSubKey == NULL )
  647. {
  648. delete [] szTextualSid;
  649. return;
  650. }
  651. //
  652. // Prepare SubKey path by concatinating the fixed+variable paths
  653. //
  654. strcpy( szSubKey, szProfileList ); // Already correct size allocated based on strlen, no overflow/Attack.
  655. strcat( szSubKey, szTextualSid );
  656. lRet = RegOpenKeyExA(
  657. HKEY_LOCAL_MACHINE,
  658. szSubKey,
  659. 0,
  660. KEY_QUERY_VALUE,
  661. &hKey
  662. );
  663. if( lRet != ERROR_SUCCESS )
  664. {
  665. delete [] szTextualSid;
  666. delete [] szSubKey;
  667. return;
  668. }
  669. //
  670. // Get ProfileImagePath
  671. //
  672. lRet = RegQueryValueExA(
  673. hKey,
  674. "ProfileImagePath",
  675. NULL,
  676. NULL,
  677. ( LPBYTE )szPath,
  678. &cbPath
  679. );
  680. if( lRet != ERROR_SUCCESS )
  681. {
  682. delete [] szTextualSid;
  683. delete [] szSubKey;
  684. return;
  685. }
  686. //
  687. // Expand ProfileImagePath
  688. //
  689. if( ExpandEnvironmentStringsA( szPath, szExpandedPath, MAX_PATH ) == 0 )
  690. {
  691. delete [] szTextualSid;
  692. delete [] szSubKey;
  693. RegCloseKey( hKey );
  694. return;
  695. }
  696. //
  697. // Enable SeRestorePrivilege for RegLoadKey
  698. //
  699. #if 0
  700. SetCurrentPrivilege( SE_RESTORE_NAME, TRUE );
  701. #endif
  702. //
  703. // Load the users registry hive
  704. //
  705. lRet = RegLoadKeyA( HKEY_USERS, szTextualSid, szExpandedPath );
  706. if( lRet != ERROR_SUCCESS )
  707. {
  708. delete [] szTextualSid;
  709. delete [] szSubKey;
  710. RegCloseKey( hKey );
  711. return;
  712. }
  713. //
  714. // Disable SeRestorePrivilege
  715. //
  716. #if 0
  717. SetCurrentPrivilege( SE_RESTORE_NAME, FALSE );
  718. #endif
  719. //
  720. // Free resources
  721. //
  722. if( hKey != NULL )
  723. {
  724. RegCloseKey( hKey );
  725. }
  726. if( szSubKey != NULL )
  727. {
  728. delete [] szSubKey;
  729. }
  730. }
  731. else
  732. {
  733. if( hK3 != NULL )
  734. {
  735. RegCloseKey( hK3 );
  736. }
  737. }
  738. //
  739. // Get path name to tlntsvr.exe
  740. //
  741. if( !GetModuleFileNameA( NULL, szPathName, MAX_PATH-1 ) )
  742. {
  743. delete [] szTextualSid;
  744. return;
  745. }
  746. //
  747. // Nuke the trailing "tlntsvr.exe"
  748. //
  749. LPSTR pSlash = strrchr( szPathName, '\\' );
  750. if( pSlash == NULL )
  751. {
  752. delete [] szTextualSid;
  753. return;
  754. }
  755. else
  756. {
  757. *pSlash = '\0';
  758. }
  759. LPSTR szTlntsess = "tlntsess.exe";
  760. int ch = '\\';
  761. LPSTR pBackSlash;
  762. //
  763. // Replace all '\\' with '_' This format is required for the console to
  764. // interpret the key.
  765. //
  766. while ( 1 )
  767. {
  768. pBackSlash = strchr( szPathName, ch );
  769. if( pBackSlash == NULL )
  770. {
  771. break;
  772. }
  773. else
  774. {
  775. *pBackSlash = '_';
  776. }
  777. }
  778. //
  779. // Append "tlntsess.exe" to the path
  780. //
  781. strcat( szPathName, "_" );
  782. strcat( szPathName, szTlntsess );
  783. HKEY hk2;
  784. //
  785. // The key we need to create is of the form:
  786. // HKEY_USERS\S-1-5-21-2127521184-1604012920-1887927527-65937\Console\C:_SFU_Telnet_tlntsess.exe
  787. //
  788. unsigned int nBytes = ( strlen( szTextualSid ) + strlen( "Console" ) + strlen( szPathName ) + 3 ) * sizeof( CHAR );
  789. lpszKey = (LPSTR) new CHAR[nBytes];
  790. if( !lpszKey )
  791. {
  792. delete[] szTextualSid;
  793. return;
  794. }
  795. SfuZeroMemory(lpszKey, nBytes);
  796. strcpy( lpszKey, szTextualSid );
  797. strcat( lpszKey, "\\" );
  798. strcat( lpszKey, "Console" );
  799. strcat( lpszKey, "\\" );
  800. strcat( lpszKey, szPathName );
  801. //
  802. //
  803. // Freeup TextualSid
  804. delete [] szTextualSid;
  805. //Need to set this in order to be able to display on Non-Jap FE machines
  806. HKEY hk;
  807. lRet = RegOpenKeyEx(
  808. HKEY_USERS,
  809. _T(".DEFAULT\\Console"),
  810. 0,
  811. KEY_SET_VALUE,
  812. &hk
  813. );
  814. if( lRet != ERROR_ACCESS_DENIED || lRet == ERROR_SUCCESS )
  815. {
  816. //
  817. // Add STRING value "FaceName " under the key HKEY_USERS\.Default\Console
  818. //
  819. if( (lRet=RegSetValueEx( hk, _T("FaceName"), 0, REG_SZ, (LPBYTE) szFaceNameDef, dwFaceNameSize )) != ERROR_SUCCESS )
  820. {
  821. RegCloseKey( hk );
  822. return;
  823. }
  824. RegCloseKey( hk );
  825. }
  826. //
  827. // Attempt to create this key
  828. //
  829. if( !RegCreateKeyA( HKEY_USERS, lpszKey, &hk2 ) )
  830. {
  831. dwSize = sizeof( DWORD );
  832. //
  833. // Add DWORD value "FontFamily = 54" under the key
  834. //
  835. if( RegSetValueEx( hk2, _T("FontFamily"), 0, REG_DWORD, (LPBYTE) &dwVal, dwSize ) != ERROR_SUCCESS )
  836. {
  837. RegCloseKey( hk2 );
  838. delete [] lpszKey;
  839. return;
  840. }
  841. //
  842. // Add DWORD value "CodePage " under the key
  843. //
  844. if( RegSetValueEx( hk2, _T("CodePage"), 0, REG_DWORD, (LPBYTE) &dwCodePage, dwSize ) != ERROR_SUCCESS )
  845. {
  846. RegCloseKey( hk2 );
  847. delete [] lpszKey;
  848. return;
  849. }
  850. //
  851. // Add DWORD value "Font Size " under the key
  852. //
  853. if( RegSetValueEx( hk2, _T("FontSize"), 0, REG_DWORD, (LPBYTE) &dwFontSize, dwSize ) != ERROR_SUCCESS )
  854. {
  855. RegCloseKey( hk2 );
  856. delete [] lpszKey;
  857. return;
  858. }
  859. dwVal = 400;
  860. //
  861. // Add DWORD value "FontWeight = 400" under the key
  862. //
  863. if( RegSetValueEx( hk2, _T("FontWeight"), 0, REG_DWORD, (LPBYTE) &dwVal, dwSize ) != ERROR_SUCCESS )
  864. {
  865. RegCloseKey( hk2 );
  866. delete [] lpszKey;
  867. return;
  868. }
  869. dwVal = 0;
  870. //
  871. // Add DWORD value "HistoryNoDup = 0" under the key
  872. //
  873. if( RegSetValueEx( hk2, _T("HistoryNoDup"), 0, REG_DWORD, (LPBYTE) &dwVal, dwSize ) != ERROR_SUCCESS )
  874. {
  875. RegCloseKey( hk2 );
  876. delete [] lpszKey;
  877. return;
  878. }
  879. //
  880. // Add STRING value "FaceName" under the key
  881. //
  882. if( RegSetValueEx( hk2, _T("FaceName"), 0, REG_SZ, (LPBYTE) szFaceNameDef, dwFaceNameSize ) != ERROR_SUCCESS )
  883. {
  884. RegCloseKey( hk2 );
  885. delete [] lpszKey;
  886. return;
  887. }
  888. RegCloseKey( hk2 );
  889. }
  890. if(lpszKey != NULL)
  891. {
  892. delete [] lpszKey;
  893. }
  894. return;
  895. }
  896. #ifdef ENABLE_LOGON_SCRIPT
  897. void
  898. CShell::GetUserScriptName( LPWSTR *szArgBuf, LPWSTR szUserScriptPath )
  899. {
  900. _chASSERT( szUserScriptPath != NULL );
  901. _chASSERT( szArgBuf != NULL );
  902. _chASSERT( pServerName != NULL );
  903. DWORD dwSize = 0;
  904. LPWSTR expandedScript = NULL;
  905. LPWSTR shellName = NULL;
  906. LPWSTR szTmp = NULL;
  907. wcscpy( szUserScriptPath, L"" );
  908. if( !AllocateNExpandEnvStrings( pLogonScriptPath, &expandedScript ) )
  909. {
  910. return;
  911. }
  912. dwSize = wcslen( pServerName ) + wcslen( DC_LOGON_SCRIPT_PATH) +
  913. wcslen( LOCALHOST_LOGON_SCRIPT_PATH ) + wcslen( expandedScript ) +
  914. + 1;
  915. *szArgBuf = new WCHAR[ dwSize ];
  916. if( !*szArgBuf )
  917. {
  918. return;
  919. }
  920. SfuZeroMemory( *szArgBuf, dwSize );
  921. if( m_bIsLocalHost && !IsThisMachineDC() )
  922. {
  923. LPWSTR szSysDir = NULL;
  924. if( GetTheSystemDirectory( &szSysDir ) )
  925. {
  926. //logon script path
  927. wsprintf( szUserScriptPath, L"%s%s", szSysDir, LOCALHOST_LOGON_SCRIPT_PATH ); // NO size info, Baskar. Attack ?
  928. wsprintf( *szArgBuf, L"%s%s%s",
  929. szSysDir, LOCALHOST_LOGON_SCRIPT_PATH, expandedScript ); // NO size info, Baskar. Attack ?
  930. }
  931. delete[] szSysDir;
  932. }
  933. else
  934. {
  935. //When NTLM authenticated, we are unable to access the logon script on the net share.
  936. //This gives "access denied error" in the session. To avoid this, don't exec logon script....
  937. if( !m_pSession->CIoHandler::m_bNTLMAuthenticated )
  938. {
  939. //logon script path
  940. wsprintf( szUserScriptPath, L"%s%s", pServerName, DC_LOGON_SCRIPT_PATH ); // NO size info, Baskar. Attack ?
  941. wsprintf( *szArgBuf, L"%s%s%s",
  942. pServerName, DC_LOGON_SCRIPT_PATH, expandedScript ); // NO size info, Baskar. Attack ?
  943. }
  944. }
  945. wcscat( szUserScriptPath, expandedScript );
  946. szTmp = wcsrchr( szUserScriptPath, L'\\' );
  947. if( szTmp )
  948. {
  949. *szTmp = L'\0';
  950. }
  951. else
  952. {
  953. szUserScriptPath[0] = 0;
  954. }
  955. delete[] expandedScript;
  956. delete[] shellName;
  957. }
  958. #endif
  959. void
  960. CShell::GetScriptName( LPWSTR *szShell, LPWSTR *szArgBuf )
  961. {
  962. _chASSERT( szArgBuf );
  963. _chASSERT( szShell );
  964. TCHAR szUserScriptPath[ MAX_PATH + 1 ];
  965. LPWSTR szUserScriptCmd = NULL;
  966. DWORD dwSize = 0;
  967. LPWSTR script1 = NULL;
  968. *szShell = NULL;
  969. *szArgBuf = NULL;
  970. if( !AllocateNExpandEnvStrings( m_pSession->m_pszDefaultShell, szShell ) )
  971. {
  972. goto GetScriptNameAbort;
  973. }
  974. _TRACE(TRACE_DEBUGGING,L"szShell = %s",*szShell);
  975. if( !AllocateNExpandEnvStrings( m_pSession->m_pszLoginScript, &script1 ) )
  976. {
  977. goto GetScriptNameAbort;
  978. }
  979. _TRACE(TRACE_DEBUGGING,L"script1l = %s",script1);
  980. #ifdef ENABLE_LOGON_SCRIPT
  981. if( pLogonScriptPath && ( wcscmp( pLogonScriptPath, L"" ) != 0 ) )
  982. {
  983. //User specific logon script is present. Execute this in a separate cmd.
  984. //Get the shell, its commandline and also path for user script
  985. GetUserScriptName( &szUserScriptCmd, szUserScriptPath );
  986. if( !szUserScriptCmd )
  987. {
  988. goto GetScriptNameAbort;
  989. }
  990. _TRACE(TRACE_DEBUGGING,L"szUserScriptCmd = %s",szUserScriptCmd);
  991. //This would update m_lpEnv if it is not null or the environment of current
  992. //process for inheritance
  993. if(FALSE == InjectUserScriptPathIntoPath( szUserScriptPath ))
  994. {
  995. goto GetScriptNameAbort;
  996. }
  997. dwSize += wcslen( AND ) +
  998. wcslen( szUserScriptCmd );
  999. }
  1000. #endif
  1001. if( m_pSession->CSession::m_pszDifferentShell && m_pSession->CSession::m_pszDifferentShell[0] != L'\0' )
  1002. {
  1003. dwSize += wcslen( AND ) +
  1004. wcslen( m_pSession->CSession::m_pszDifferentShell ) +
  1005. wcslen( AND ) +
  1006. wcslen( EXIT_CMD );
  1007. }
  1008. /* the arg is of the form :/q /k c:\sfu\telnet\userlogin.cmd *///&&c:\sfu\telnet\telnetlogin.cmd
  1009. dwSize += wcslen(m_pSession->CSession::m_pszSwitchToKeepShellRunning) +
  1010. wcslen(L" ") +
  1011. wcslen( script1 ) +
  1012. 1;
  1013. *szArgBuf = new WCHAR[ dwSize ];
  1014. if( !*szArgBuf )
  1015. {
  1016. goto GetScriptNameAbort;
  1017. }
  1018. wsprintf(*szArgBuf,L"%s%s",m_pSession->CSession::m_pszSwitchToKeepShellRunning,L" "); // NO size info, Baskar. Attack ?
  1019. #ifdef ENABLE_LOGON_SCRIPT
  1020. if( pLogonScriptPath && ( wcscmp( pLogonScriptPath, L"" ) != 0 ) )
  1021. {
  1022. wcscat( *szArgBuf, szUserScriptCmd );
  1023. wcscat( *szArgBuf, AND );
  1024. }
  1025. #endif
  1026. _TRACE(TRACE_DEBUGGING,L"szArgBuf became = %s",*szArgBuf);
  1027. wcscat( *szArgBuf, script1 );
  1028. if( m_pSession->CSession::m_pszDifferentShell && m_pSession->CSession::m_pszDifferentShell[0] != L'\0' )
  1029. {
  1030. wcscat( *szArgBuf, AND );
  1031. wcscat( *szArgBuf, m_pSession->CSession::m_pszDifferentShell );
  1032. wcscat( *szArgBuf, AND );
  1033. wcscat( *szArgBuf, EXIT_CMD );
  1034. }
  1035. GetScriptNameAbort:
  1036. #ifdef ENABLE_LOGON_SCRIPT
  1037. if(szUserScriptCmd)
  1038. {
  1039. delete[] szUserScriptCmd;
  1040. }
  1041. #endif
  1042. if(script1)
  1043. {
  1044. delete[] script1;
  1045. }
  1046. _TRACE( TRACE_DEBUGGING, L"Argument for Shell: %s", *szArgBuf );
  1047. _TRACE( TRACE_DEBUGGING, L"Command Shell: %s", *szShell );
  1048. }
  1049. /*Mem allocated by the function; to be released by the caller */
  1050. bool
  1051. CShell::GetTheSystemDirectory( LPWSTR *szDir )
  1052. {
  1053. WORD wSize = MAX_PATH;
  1054. DWORD dwErr = 0;
  1055. DWORD dwStatus = 0;
  1056. retry:
  1057. *szDir = new WCHAR[ wSize ];
  1058. if( !*szDir )
  1059. {
  1060. return( FALSE );
  1061. }
  1062. dwStatus = GetSystemDirectory( *szDir, wSize );
  1063. if( !dwStatus )
  1064. {
  1065. delete[] ( *szDir );
  1066. dwErr = GetLastError();
  1067. if( dwErr != ERROR_INSUFFICIENT_BUFFER )
  1068. {
  1069. LogFormattedGetLastError( EVENTLOG_ERROR_TYPE, 0, dwErr );
  1070. return( FALSE );
  1071. }
  1072. wSize += MAX_PATH;
  1073. goto retry;
  1074. }
  1075. return ( TRUE );
  1076. }
  1077. bool
  1078. CShell::GetSystemDrive()
  1079. {
  1080. if( GetTheSystemDirectory( &wideHomeDir ) )
  1081. {
  1082. DWORD i=0;
  1083. while( wideHomeDir[ i ] != L'\0' && wideHomeDir[ i++ ] != L':' )
  1084. {
  1085. //Do nothing
  1086. }
  1087. wideHomeDir[ i++ ] = L'\\';
  1088. wideHomeDir[ i ] = L'\0';
  1089. return( TRUE );
  1090. }
  1091. return( FALSE );
  1092. }
  1093. bool
  1094. CShell::OnDataFromCmdPipe()
  1095. {
  1096. // Sendit over socket.
  1097. DWORD dwNumBytesRead = 0;
  1098. FinishIncompleteIo( m_hReadFromCmd, &m_oReadFromCmd, &dwNumBytesRead );
  1099. if( m_pSession->CScraper::m_dwTerm & TERMVTNT )
  1100. {
  1101. PUCHAR pVtntChars = NULL;
  1102. DWORD dwSize = 0;
  1103. m_pSession->CRFCProtocol::StrToVTNTResponse( ( CHAR * )m_pucDataFromCmd, dwNumBytesRead,
  1104. ( VOID ** )&pVtntChars, &dwSize );
  1105. m_pSession->CScraper::SendBytes( pVtntChars, dwSize );
  1106. delete[] pVtntChars;
  1107. }
  1108. else
  1109. {
  1110. m_pSession->CScraper::SendBytes( m_pucDataFromCmd, dwNumBytesRead );
  1111. }
  1112. if( !IssueReadFromCmd() )
  1113. {
  1114. return( FALSE );
  1115. }
  1116. return( TRUE );
  1117. }
  1118. bool
  1119. CShell::IssueReadFromCmd()
  1120. {
  1121. DWORD dwRequestedIoSize = MAX_WRITE_SOCKET_BUFFER;
  1122. if( !ReadFile( m_hReadFromCmd, m_pucDataFromCmd,
  1123. dwRequestedIoSize, &m_dwDataSizeFromCmd, &m_oReadFromCmd ) )
  1124. {
  1125. DWORD dwError = GetLastError( );
  1126. if( ( dwError == ERROR_MORE_DATA ) || ( dwError != ERROR_IO_PENDING ) )
  1127. {
  1128. LogFormattedGetLastError( EVENTLOG_ERROR_TYPE, MSG_ERR_READCMD, dwError );
  1129. _TRACE( TRACE_DEBUGGING, " Error: ReadFile -- 0x%1x ", dwError );
  1130. return ( FALSE );
  1131. }
  1132. }
  1133. return( TRUE );
  1134. }
  1135. bool
  1136. CShell::StartProcess ( )
  1137. {
  1138. DWORD dwStatus;
  1139. LPWSTR szArgBuf = NULL;
  1140. LPWSTR szShell = NULL;
  1141. PROCESS_INFORMATION pi, temp_pi;
  1142. STARTUPINFO si, temp_si;
  1143. bool bTryOnceAgain = true;
  1144. bool bRetVal = TRUE;
  1145. bool impersonating_client = FALSE;
  1146. HANDLE hStdError = NULL;
  1147. HANDLE hHandleToDuplicate = NULL;
  1148. DWORD dwExitCode = 0;
  1149. PSECURITY_DESCRIPTOR psd = NULL;
  1150. LPTSTR desktop_name = NULL;
  1151. LPTSTR winsta_name = NULL;
  1152. LPTSTR winsta_desktop = NULL;
  1153. HWINSTA winsta_service = NULL;
  1154. DWORD required = 0;
  1155. /*++
  1156. MSRC issue 567.
  1157. To generate random numbers, use Crypt...() functions. Acquire a crypt context at the beginning of
  1158. ListenerThread and release the context at the end of the thread. If acquiring the context fails,
  1159. the service fails to start since we do not want to continue with weak pipe names.
  1160. initialize the random number generator
  1161. --*/
  1162. if (!CryptAcquireContext(&g_hProv,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT))
  1163. {
  1164. _TRACE(TRACE_DEBUGGING,L"Acquiring crypt context failed with error %d",GetLastError());
  1165. return FALSE;
  1166. }
  1167. if( !CreateIOHandles() )
  1168. {
  1169. return( FALSE );
  1170. }
  1171. if( m_pSession->CSession::m_bIsStreamMode )
  1172. {
  1173. TELNET_CLOSE_HANDLE( m_pSession->CScraper::m_hConBufOut );
  1174. InitializeOverlappedStruct( &m_oReadFromCmd );
  1175. m_pucDataFromCmd = new UCHAR[ MAX_WRITE_SOCKET_BUFFER ];
  1176. if( !m_pucDataFromCmd )
  1177. {
  1178. return( FALSE );
  1179. }
  1180. m_hReadFromCmd = NULL;
  1181. m_hWriteByCmd = NULL;
  1182. if(!TnCreateDefaultSecDesc(&psd, GENERIC_ALL&
  1183. ~(WRITE_DAC | WRITE_OWNER | DELETE)))
  1184. {
  1185. return(FALSE);
  1186. }
  1187. if( !CreateReadOrWritePipe( &m_hReadFromCmd, &m_hWriteByCmd, (SECURITY_DESCRIPTOR *)psd, READ_PIPE ) )
  1188. {
  1189. if(psd)
  1190. {
  1191. free(psd);
  1192. }
  1193. return( FALSE );
  1194. }
  1195. //The following is for aesthetics
  1196. if( !m_pSession->CIoHandler::m_bNTLMAuthenticated )
  1197. {
  1198. DWORD dwNumWritten = 0;
  1199. UCHAR pBuf[] = { '\r', '\n', '\r', '\n' };
  1200. _chVERIFY2( WriteFile( m_hWriteByCmd, pBuf, sizeof( pBuf ), &dwNumWritten, NULL ) );
  1201. }
  1202. hHandleToDuplicate = m_hWriteByCmd;
  1203. }
  1204. else
  1205. {
  1206. hHandleToDuplicate = m_pSession->CScraper::m_hConBufOut;
  1207. }
  1208. if( !DuplicateHandle( GetCurrentProcess(), hHandleToDuplicate,
  1209. GetCurrentProcess(), &hStdError,0,
  1210. TRUE, DUPLICATE_SAME_ACCESS) )
  1211. {
  1212. hStdError = m_pSession->CScraper::m_hConBufOut;
  1213. }
  1214. if (!
  1215. create_desktop_for_this_session(m_pSession->CSession::m_hToken, &desktop_name))
  1216. {
  1217. bRetVal = FALSE;
  1218. goto ExitOnError;
  1219. }
  1220. winsta_service = GetProcessWindowStation();
  1221. if(winsta_service == NULL)
  1222. {
  1223. bRetVal = FALSE;
  1224. goto ExitOnError;
  1225. }
  1226. //bound to fail the first time. Get the size required by the winsta_name
  1227. GetUserObjectInformation( winsta_service,
  1228. UOI_NAME,
  1229. winsta_name,
  1230. 0,
  1231. &required);
  1232. winsta_name = (LPTSTR) malloc (required);
  1233. if(winsta_name == NULL)
  1234. {
  1235. bRetVal = FALSE;
  1236. goto ExitOnError;
  1237. }
  1238. if(!GetUserObjectInformation( winsta_service,
  1239. UOI_NAME,
  1240. winsta_name,
  1241. required,
  1242. &required))
  1243. {
  1244. bRetVal = FALSE;
  1245. goto ExitOnError;
  1246. }
  1247. required = _tcslen(winsta_name)+_tcslen(desktop_name)+2; //+2 - 1 for '\\' and 1 for NULL
  1248. winsta_desktop = (LPTSTR) malloc(required*sizeof(TCHAR));
  1249. if(winsta_desktop == NULL)
  1250. {
  1251. bRetVal = FALSE;
  1252. goto ExitOnError;
  1253. }
  1254. _sntprintf(winsta_desktop,required,TEXT("%s\\%s"),winsta_name,desktop_name);
  1255. FillProcessStartupInfo( &si, m_pSession->CScraper::m_hConBufIn,
  1256. hHandleToDuplicate, hStdError, winsta_desktop );
  1257. SfuZeroMemory((void *)&temp_si, sizeof(temp_si));
  1258. temp_si.cb = sizeof( STARTUPINFO );
  1259. temp_si.lpDesktop = winsta_desktop;
  1260. temp_si.wShowWindow = SW_HIDE;
  1261. AllocNCpyWStr( &wideHomeDir, pHomeDir );
  1262. if( !wideHomeDir || wcscmp( wideHomeDir, L"" ) == 0 )
  1263. {
  1264. if ( wideHomeDir )
  1265. delete[] wideHomeDir;
  1266. GetSystemDrive( );
  1267. }
  1268. else
  1269. {
  1270. //Is it a network drive??
  1271. if( memcmp(L"\\\\", wideHomeDir, 4 ) == 0 )
  1272. {
  1273. GetUsersHomeDirectory( wideHomeDir );
  1274. }
  1275. }
  1276. m_lpEnv = NULL;
  1277. if( m_pSession-> m_bNtVersionGTE5 && fnP_CreateEnvironmentBlock )
  1278. {
  1279. if(!ImpersonateLoggedOnUser(m_pSession->CSession::m_hToken))
  1280. {
  1281. bRetVal = FALSE;
  1282. goto ExitOnError;
  1283. }
  1284. if( !fnP_CreateEnvironmentBlock( &( m_lpEnv ),
  1285. m_pSession->CSession::m_hToken, FALSE ) )
  1286. {
  1287. _TRACE( TRACE_DEBUGGING, "Error: CreateEnvironmentBlock()"
  1288. " - 0x%lx", GetLastError());
  1289. m_lpEnv = NULL;
  1290. }
  1291. if(!RevertToSelf())
  1292. {
  1293. bRetVal = FALSE;
  1294. goto ExitOnError;
  1295. }
  1296. }
  1297. //This function will insert some new variables in to the env
  1298. GetEnvVarData();
  1299. if( m_lpEnv )
  1300. {
  1301. ExportEnvVariables();
  1302. }
  1303. else
  1304. {
  1305. // Let the cmd inherit
  1306. SetEnvVariables();
  1307. }
  1308. GetScriptName( &szShell, &szArgBuf );
  1309. CleanupClientToken(m_pSession->CSession::m_hToken); // We don't care whether it succeeded or not
  1310. SetConsoleCtrlHandler( NULL, FALSE );
  1311. //call CreateProcessWithTokenW() CREATE_SUSPENDED on a dummy process. This will effectively load the profile for you.
  1312. //Save this process handle away
  1313. //service will use CreateProcessAsUser(), as it has in the past.
  1314. //call TerminateProcess() on the dummy process when the �real� process launched by
  1315. //CreateProcessAsUser() dies. This had to be done since
  1316. //CreateProcessWithTokenW() did not work as expected. There were some problems
  1317. //in associating the input output redirection handles with cmd.exe
  1318. if(!CreateProcessWithTokenW(m_pSession->CSession::m_hToken,
  1319. LOGON_WITH_PROFILE,
  1320. szShell,
  1321. szArgBuf,
  1322. CREATE_UNICODE_ENVIRONMENT | CREATE_SUSPENDED,
  1323. m_lpEnv,
  1324. NULL,
  1325. &temp_si,
  1326. &temp_pi)
  1327. )
  1328. {
  1329. DWORD dwLastError;
  1330. dwLastError = GetLastError();
  1331. LogFormattedGetLastError( EVENTLOG_ERROR_TYPE, MSG_ERRCMD, dwLastError );
  1332. _TRACE( TRACE_DEBUGGING, "Error: CreateProcessWithToken() - 0x%lx",
  1333. dwLastError );
  1334. _chASSERT( 0 );
  1335. bRetVal = FALSE;
  1336. SetConsoleCtrlHandler( NULL, TRUE );
  1337. goto ExitOnError;
  1338. }
  1339. else
  1340. {
  1341. m_hTempProcess = temp_pi.hProcess;
  1342. TELNET_CLOSE_HANDLE( temp_pi.hThread );
  1343. }
  1344. //You need to impersonate around CreateProcessAsUserA. Otherwise,
  1345. //if lpCurrentDir parameter is a network resource, the call will fail in the
  1346. //context of system account. Could not access the remote drive when the process
  1347. //is called with CreateProcessA alone. Don't know why??
  1348. if( !ImpersonateLoggedOnUser(m_pSession->CSession::m_hToken))
  1349. {
  1350. bRetVal = false;
  1351. goto ExitOnError;
  1352. }
  1353. impersonating_client = true;
  1354. try_again:
  1355. if( !CreateProcessAsUser( m_pSession->CSession::m_hToken, szShell,
  1356. szArgBuf,
  1357. NULL, NULL, TRUE,
  1358. CREATE_UNICODE_ENVIRONMENT | CREATE_SEPARATE_WOW_VDM,
  1359. m_lpEnv, NULL, &si, &pi ) )
  1360. {
  1361. DWORD dwLastError;
  1362. dwLastError = GetLastError();
  1363. if( dwLastError == ERROR_DIRECTORY && bTryOnceAgain )
  1364. {
  1365. bTryOnceAgain = false;
  1366. delete[] wideHomeDir;
  1367. GetSystemDrive( );
  1368. goto try_again;
  1369. }
  1370. LogFormattedGetLastError( EVENTLOG_ERROR_TYPE, MSG_ERRCMD, dwLastError );
  1371. _TRACE( TRACE_DEBUGGING, "Error: CreateProcessAsUserA() - 0x%lx",
  1372. dwLastError );
  1373. _chASSERT( 0 );
  1374. bRetVal = FALSE;
  1375. SetConsoleCtrlHandler( NULL, TRUE );
  1376. goto ExitOnError;
  1377. }
  1378. _chVERIFY2( GetExitCodeProcess( pi.hProcess, &dwExitCode ) );
  1379. if( dwExitCode != STILL_ACTIVE )
  1380. {
  1381. bRetVal = FALSE;
  1382. goto ExitOnError;
  1383. }
  1384. m_hProcess = pi.hProcess;
  1385. TELNET_CLOSE_HANDLE( pi.hThread );
  1386. SetConsoleCtrlHandler( NULL, TRUE );
  1387. ExitOnError:
  1388. TELNET_CLOSE_HANDLE( hStdError );
  1389. TELNET_CLOSE_HANDLE( m_pSession->CScraper::m_hConBufOut );
  1390. if(winsta_service)
  1391. {
  1392. CloseWindowStation(winsta_service);
  1393. }
  1394. if(impersonating_client && (! RevertToSelf()))
  1395. {
  1396. LogFormattedGetLastError(EVENTLOG_ERROR_TYPE, TELNET_MSG_REVERTSELFFAIL, GetLastError());
  1397. bRetVal = false;
  1398. }
  1399. if(psd)
  1400. {
  1401. free(psd);
  1402. }
  1403. if(desktop_name)
  1404. {
  1405. LocalFree(desktop_name);
  1406. }
  1407. if(winsta_name)
  1408. {
  1409. free(winsta_name);
  1410. }
  1411. if(winsta_desktop)
  1412. {
  1413. free(winsta_desktop);
  1414. }
  1415. delete[] wideHomeDir;
  1416. delete[] szShell;
  1417. delete[] szArgBuf;
  1418. return ( bRetVal );
  1419. }
  1420. //Set "homedir" to the home directory of the user. Make a net connection if the //home directory is remote.
  1421. //System account can't access the network resources. You need to impersonate.
  1422. bool CShell::GetUsersHomeDirectory( LPWSTR homedir )
  1423. {
  1424. LPWSTR wsPathName = NULL;
  1425. LPWSTR wsNetName = NULL;
  1426. NETRESOURCE NetResource;
  1427. LPWSTR p;
  1428. int i, count, NthBackSlash;
  1429. bool result = true;
  1430. DWORD dwAddError = ERROR_SUCCESS;
  1431. LPWSTR szSaveHomeDir = NULL;
  1432. _TRACE( TRACE_DEBUGGING, "GetUsersHomeDirectory()");
  1433. _chASSERT( homedir != NULL );
  1434. // it is a network share
  1435. // mount it and return drive:path
  1436. if( !ImpersonateLoggedOnUser(m_pSession->CSession::m_hToken) )
  1437. {
  1438. wcscpy( homedir, L"C:\\" );
  1439. _TRACE( TRACE_DEBUGGING, "Error: ImpersonateLoggedonUser() --"
  1440. "0x%1x \n", GetLastError() );
  1441. return false;
  1442. }
  1443. if( !AllocNCpyWStr( &( wsPathName ), homedir) )
  1444. {
  1445. goto ExitOnError;
  1446. }
  1447. if( !AllocNCpyWStr( &( wsNetName ), homedir) )
  1448. {
  1449. goto ExitOnError;
  1450. }
  1451. if( !AllocNCpyWStr( &( szSaveHomeDir ), homedir) )
  1452. {
  1453. goto ExitOnError;
  1454. }
  1455. // find the fourth backslash - everything from there on is pathname
  1456. // This approach is sufficient for SMB. But, In NFS, \ is a valid char
  1457. // inside a share name. So, by trial and error, connect to the exact share
  1458. // name.
  1459. NthBackSlash = 4;
  1460. do
  1461. {
  1462. dwAddError = ERROR_SUCCESS;
  1463. for( i=0,count = 0, p =homedir; *p; ++p, ++i )
  1464. {
  1465. if( *p==L'\\' )
  1466. {
  1467. if( ++count == NthBackSlash )
  1468. break;
  1469. }
  1470. wsNetName[ i ] = homedir[ i ];
  1471. }
  1472. wsNetName[i] = L'\0';
  1473. i=0;
  1474. while( *p )
  1475. {
  1476. wsPathName[ i++ ] = *p++;
  1477. }
  1478. wsPathName[ i ] = L'\0';
  1479. if( count == NthBackSlash )
  1480. {
  1481. _snwprintf( homedir,(wcslen(pHomeDrive)+wcslen(wsPathName)),L"%s%s", pHomeDrive,
  1482. wsPathName ); // NO size info, Baskar. Attack ?
  1483. }
  1484. else
  1485. {
  1486. _snwprintf( homedir,wcslen(pHomeDrive),L"%s\\", pHomeDrive ); // NO size info, Baskar. Attack ?
  1487. }
  1488. NetResource.lpRemoteName = wsNetName;
  1489. NetResource.lpLocalName = pHomeDrive;
  1490. NetResource.lpProvider = NULL;
  1491. NetResource.dwType = RESOURCETYPE_DISK;
  1492. if( WNetAddConnection2( &NetResource, NULL, NULL, 0 ) != NO_ERROR )
  1493. {
  1494. dwAddError = GetLastError();
  1495. if( dwAddError == ERROR_ALREADY_ASSIGNED)
  1496. {
  1497. }
  1498. else
  1499. {
  1500. if( dwAddError == ERROR_BAD_NET_NAME && count == NthBackSlash )
  1501. {
  1502. wcscpy( homedir, szSaveHomeDir );
  1503. }
  1504. else
  1505. {
  1506. wcscpy( homedir, L"C:\\" );
  1507. _TRACE( TRACE_DEBUGGING, "Error: WNetAddConnection2() --"
  1508. " 0x%1x", dwAddError );
  1509. result = false;
  1510. dwAddError = ERROR_SUCCESS; //Get out of the loop
  1511. }
  1512. }
  1513. }
  1514. NthBackSlash++; // It may be NFS share and \ may be part of share name.
  1515. }
  1516. //ERROR_BAD_NET_NAME: The network name cannot be found
  1517. while( dwAddError == ERROR_BAD_NET_NAME);
  1518. ExitOnError:
  1519. if(! RevertToSelf())
  1520. {
  1521. LogFormattedGetLastError(EVENTLOG_ERROR_TYPE, TELNET_MSG_REVERTSELFFAIL, GetLastError());
  1522. result = false;
  1523. _TRACE( TRACE_DEBUGGING, "Error: RevertToSelf() -- 0x%1x",
  1524. GetLastError() );
  1525. }
  1526. delete[] szSaveHomeDir;
  1527. delete[] wsPathName;
  1528. delete[] wsNetName;
  1529. return result;
  1530. }
  1531. //Get the user preference related info
  1532. bool CShell::GetNFillUserPref(LPWSTR serverName, LPWSTR user)
  1533. {
  1534. LPBYTE bufPtr = NULL;
  1535. LPUSER_INFO_3 userInfo3;
  1536. DWORD dwStatus = 0;
  1537. bool bRetVal = false;
  1538. BOOL bReturn = FALSE;
  1539. bReturn = ImpersonateLoggedOnUser( m_pSession->CSession::m_hToken );
  1540. if(!bReturn)
  1541. {
  1542. bRetVal = false;
  1543. goto Done;
  1544. }
  1545. if( ( dwStatus = NetUserGetInfo( serverName, user, 3, &bufPtr ) )== NERR_Success )
  1546. {
  1547. userInfo3 = ( LPUSER_INFO_3 ) bufPtr;
  1548. if( !AllocNCpyWStr( &pProfilePath, userInfo3->usri3_profile ) )
  1549. {
  1550. goto ExitOnError;
  1551. }
  1552. if( !AllocNCpyWStr( &pLogonScriptPath, userInfo3->usri3_script_path ) )
  1553. {
  1554. goto ExitOnError;
  1555. }
  1556. if( !AllocNCpyWStr( &pHomeDir, userInfo3->usri3_home_dir ) )
  1557. {
  1558. goto ExitOnError;
  1559. }
  1560. if( !AllocNCpyWStr( &pHomeDrive, userInfo3->usri3_home_dir_drive ) )
  1561. {
  1562. goto ExitOnError;
  1563. }
  1564. ExitOnError:
  1565. NetApiBufferFree( bufPtr );
  1566. bRetVal = true;
  1567. }
  1568. else if(dwStatus == ERROR_ACCESS_DENIED && m_pSession->CIoHandler::m_bNTLMAuthenticated)
  1569. {
  1570. bRetVal = true;
  1571. }
  1572. else
  1573. {
  1574. _TRACE( TRACE_DEBUGGING, "Error: NetUserGetInfo() code : %d",dwStatus);
  1575. }
  1576. if(!RevertToSelf())
  1577. {
  1578. LogFormattedGetLastError(EVENTLOG_ERROR_TYPE, TELNET_MSG_REVERTSELFFAIL, GetLastError());
  1579. bRetVal = false;
  1580. }
  1581. Done:
  1582. return bRetVal;
  1583. }
  1584. bool
  1585. CShell::GetNameOfTheComputer()
  1586. {
  1587. LPWSTR lpBuffer = NULL;
  1588. bool bRetVal = false;
  1589. DWORD size = MAX_COMPUTERNAME_LENGTH + 3; //one for NULL and two for '\\'.
  1590. lpBuffer = new WCHAR[ size ];
  1591. if( !lpBuffer )
  1592. {
  1593. goto Done;
  1594. }
  1595. if( !GetComputerName( lpBuffer, &size ) )
  1596. {
  1597. _TRACE( TRACE_DEBUGGING, "Error: GetComputerName() -- 0x%1x",
  1598. GetLastError() );
  1599. goto Done;
  1600. }
  1601. else
  1602. {
  1603. size++;
  1604. size+= strlen("\\\\");
  1605. pServerName = new WCHAR[ size ];
  1606. if( NULL == pServerName)
  1607. {
  1608. goto Done;
  1609. }
  1610. SfuZeroMemory((void *)pServerName,size*sizeof(WCHAR));
  1611. _snwprintf( pServerName, size -1,L"%s%s", L"\\\\", lpBuffer ); // NO overflow, calculated size already.
  1612. }
  1613. bRetVal = true;
  1614. Done:
  1615. if(lpBuffer)
  1616. delete[] lpBuffer;
  1617. return( bRetVal );
  1618. }
  1619. /*
  1620. AreYouHostingTheDomain opens the local LSA and finds out the domain hosted.
  1621. It then checks that agains the domain passed and returns TRUE/FALSE as appropriate.
  1622. */
  1623. BOOL CShell::AreYouHostingTheDomain(
  1624. LPTSTR lpDomain,
  1625. LPTSTR lpServer
  1626. )
  1627. {
  1628. OBJECT_ATTRIBUTES obj_attr = { 0 };
  1629. LSA_HANDLE policy;
  1630. NTSTATUS nStatus;
  1631. BOOL found = FALSE;
  1632. LSA_UNICODE_STRING name, *name_ptr = NULL;
  1633. obj_attr.Length = sizeof(obj_attr);
  1634. if (lpServer)
  1635. {
  1636. RtlInitUnicodeString(& name, lpServer);
  1637. name_ptr = & name;
  1638. }
  1639. nStatus = LsaOpenPolicy(
  1640. name_ptr,
  1641. &obj_attr,
  1642. POLICY_VIEW_LOCAL_INFORMATION | MAXIMUM_ALLOWED,
  1643. & policy
  1644. );
  1645. if (NT_SUCCESS(nStatus))
  1646. {
  1647. POLICY_ACCOUNT_DOMAIN_INFO *info;
  1648. nStatus = LsaQueryInformationPolicy(
  1649. policy,
  1650. PolicyAccountDomainInformation,
  1651. (PVOID *)&info
  1652. );
  1653. LsaClose(policy);
  1654. if (NT_SUCCESS(nStatus))
  1655. {
  1656. UNICODE_STRING ad_name;
  1657. RtlInitUnicodeString(& ad_name, lpDomain);
  1658. found = RtlEqualUnicodeString(& ad_name, & (info->DomainName), TRUE); // case insensitive check
  1659. LsaFreeMemory(info);
  1660. }
  1661. }
  1662. return found;
  1663. }
  1664. bool CShell::GetDomainController(LPTSTR lpDomain, LPTSTR lpServer)
  1665. {
  1666. NTSTATUS nStatus;
  1667. TCHAR *sz1stDCName = NULL;
  1668. TCHAR *sz2ndDCName = NULL;
  1669. bool bRetVal = false;
  1670. if(lpDomain == NULL || lpServer == NULL || lstrlenW(lpDomain) <= 0)
  1671. {
  1672. bRetVal = false;
  1673. goto Done;
  1674. }
  1675. // initialize the return parameter
  1676. lpServer[0] = _T('\0');
  1677. /*
  1678. Before we proceed any further check whether we are hosting the domain
  1679. */
  1680. if (AreYouHostingTheDomain(lpDomain, NULL))
  1681. {
  1682. DWORD length = MAX_COMPUTERNAME_LENGTH + 3; //one for NULL and two for '\\'
  1683. /* Yes we are hosting the domain, so get computer name and get out */
  1684. if(!GetNameOfTheComputer())
  1685. {
  1686. lpServer[0] = _T('\0');
  1687. bRetVal = false;
  1688. goto Done;
  1689. }
  1690. if(pServerName)
  1691. _tcsncpy(lpServer,pServerName,length);
  1692. bRetVal = true;
  1693. goto Done;
  1694. }
  1695. /*
  1696. Get a domain controller for the domain we are joined to
  1697. */
  1698. nStatus = NetGetAnyDCName( NULL, NULL, ( LPBYTE * )&sz1stDCName );
  1699. if(nStatus == NERR_Success )
  1700. {
  1701. /* The domain we want is that the one we are joined to ? */
  1702. if (AreYouHostingTheDomain(lpDomain, sz1stDCName) )
  1703. {
  1704. lstrcpy(lpServer, sz1stDCName); // No BO - BaskarK
  1705. NetApiBufferFree( sz1stDCName );
  1706. bRetVal = true;
  1707. goto Done;
  1708. }
  1709. /*
  1710. Since the domain we are joined to is not the one we want, let us find out whether it is in any
  1711. of the trusted list in the forest/enterprise
  1712. */
  1713. nStatus = NetGetAnyDCName( sz1stDCName, lpDomain, ( LPBYTE * )&sz2ndDCName);
  1714. if(nStatus == NERR_Success )
  1715. {
  1716. lstrcpy(lpServer, sz2ndDCName ); // No BO - BaskarK
  1717. NetApiBufferFree( sz2ndDCName );
  1718. bRetVal = true;
  1719. }
  1720. NetApiBufferFree( sz1stDCName );
  1721. }
  1722. Done:
  1723. return bRetVal;
  1724. }
  1725. //Locate and get the user info needed to load his/her profile.
  1726. bool CShell::LoadTheProfile()
  1727. {
  1728. PROFILEINFO profile = { 0 };
  1729. bool result = true;
  1730. DWORD userPathSize = MAX_PATH+1, defPathSize = MAX_PATH+1;
  1731. LPWSTR lpWideDomain = NULL ;
  1732. PDOMAIN_CONTROLLER_INFO dcInfo = NULL;
  1733. BOOL fnResult = FALSE;
  1734. _TRACE( TRACE_DEBUGGING, "LoadTheProfile()");
  1735. profile.dwSize = sizeof( profile );
  1736. profile.dwFlags = PI_NOUI;
  1737. /*
  1738. * Fill the server name and the user name to pass to the
  1739. * GetNFillUserPref function
  1740. */
  1741. ConvertSChartoWChar(m_pSession->CSession::m_pszUserName, &( profile.lpUserName ) );
  1742. profile.lpServerName = NULL;
  1743. if( !AllocNCpyWStr( &pServerName, L"") )
  1744. {
  1745. return false;
  1746. }
  1747. ConvertSChartoWChar(m_pSession->CSession::m_pszDomain, &lpWideDomain);
  1748. profile.lpServerName = new WCHAR[MAX_STRING_LENGTH];
  1749. if(profile.lpServerName == NULL)
  1750. {
  1751. result = false;
  1752. goto Done;
  1753. }
  1754. if( strcmp( m_pSession->CSession::m_pszDomain, "." ) != 0 )
  1755. {
  1756. if( GetDomainController( lpWideDomain, profile.lpServerName ) )
  1757. {
  1758. delete[] pServerName;
  1759. AllocNCpyWStr( &pServerName, profile.lpServerName );
  1760. }
  1761. }
  1762. else
  1763. {
  1764. m_bIsLocalHost = true;
  1765. GetNameOfTheComputer();
  1766. }
  1767. profile.lpProfilePath = NULL;
  1768. if(!GetNFillUserPref(profile.lpServerName, profile.lpUserName ))
  1769. {
  1770. result = false;
  1771. goto Done;
  1772. }
  1773. if( pProfilePath && wcscmp( pProfilePath, L"" ) != 0 )
  1774. {
  1775. AllocNCpyWStr( &( profile.lpProfilePath ), pProfilePath );
  1776. }
  1777. else
  1778. {
  1779. do
  1780. {
  1781. profile.lpProfilePath = new TCHAR[ userPathSize ];
  1782. if( !profile.lpProfilePath )
  1783. {
  1784. break;
  1785. }
  1786. if( !fnP_GetUserProfileDirectory )
  1787. {
  1788. break;
  1789. }
  1790. fnResult = fnP_GetUserProfileDirectory ( m_pSession->CSession::
  1791. m_hToken, profile.lpProfilePath, &userPathSize );
  1792. if (!fnResult)
  1793. {
  1794. DWORD err;
  1795. if ( ( err = GetLastError() ) != ERROR_INSUFFICIENT_BUFFER )
  1796. {
  1797. fnResult = TRUE;
  1798. _TRACE( TRACE_DEBUGGING, "Error: GetUserProfileDirecto"
  1799. "ry() -- 0x%1x", err );
  1800. }
  1801. delete[] profile.lpProfilePath;
  1802. profile.lpProfilePath = NULL;
  1803. }
  1804. } while ( !fnResult );
  1805. }
  1806. /*
  1807. * pHomeDir and pHomeDrive will be empty unless it is explicity set
  1808. * in the AD for domain users and Local User Manager for local users.
  1809. * So assign the profile directory as home directory if it is empty.
  1810. * Explorer does the same thing
  1811. */
  1812. if (pHomeDir && wcscmp(pHomeDir, L"") == 0)
  1813. {
  1814. if (profile.lpProfilePath && wcscmp(profile.lpProfilePath, L"") != 0)
  1815. {
  1816. delete[] pHomeDir;
  1817. AllocNCpyWStr(&pHomeDir, profile.lpProfilePath);
  1818. }
  1819. }
  1820. do
  1821. {
  1822. profile.lpDefaultPath = new TCHAR[ defPathSize ];
  1823. if( profile.lpDefaultPath == NULL)
  1824. {
  1825. break;
  1826. }
  1827. if( !fnP_GetDefaultUserProfileDirectory )
  1828. {
  1829. break;
  1830. }
  1831. fnResult = fnP_GetDefaultUserProfileDirectory( profile.lpDefaultPath,
  1832. &defPathSize );
  1833. if (!fnResult)
  1834. {
  1835. DWORD err;
  1836. err = GetLastError();
  1837. if ( err != ERROR_INSUFFICIENT_BUFFER )
  1838. {
  1839. fnResult = TRUE;
  1840. _TRACE( TRACE_DEBUGGING, "Error: GetDefaultUserProfile"
  1841. "Directory() -- 0x%1x", err );
  1842. }
  1843. delete[] profile.lpDefaultPath;
  1844. profile.lpDefaultPath = NULL;
  1845. }
  1846. } while ( !fnResult );
  1847. profile.lpPolicyPath = NULL;
  1848. if( fnP_LoadUserProfile )
  1849. {
  1850. if( fnP_LoadUserProfile(m_pSession->CSession::m_hToken, &profile) )
  1851. {
  1852. //assign the handle to a member from the session structure
  1853. //so that it can be unloaded.
  1854. m_hCurrUserKey = profile.hProfile;
  1855. result = true;
  1856. }
  1857. else
  1858. {
  1859. _TRACE( TRACE_DEBUGGING, "Error: LoadUserProfile() -- 0x%1x",
  1860. GetLastError() );
  1861. result = false;
  1862. }
  1863. }
  1864. /*
  1865. * Read the APPDATA folder. We need to pass this onto the environment
  1866. * variables. For a user who is logged onto the system, this variable is
  1867. * available when environment is imported. Otherwise this has to be read
  1868. * and explicitly set. Are there more of this kind?? - Investigate.
  1869. * Use CSIDL_FLAG_CREATE to have the folder created in case of a user
  1870. * who logs onto the machine for the first time ever
  1871. */
  1872. m_pwszAppDataDir = new TCHAR[MAX_PATH + 1];
  1873. if (!m_pwszAppDataDir)
  1874. {
  1875. result = false;
  1876. }
  1877. else
  1878. {
  1879. if (ImpersonateLoggedOnUser(m_pSession->CSession::m_hToken))
  1880. {
  1881. if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE,
  1882. m_pSession->m_bNtVersionGTE5 ? m_pSession->CSession::m_hToken : NULL,
  1883. // For systems earlier than Win2K this must be NULL, else you can
  1884. // pass the access token that can be used to represent a particular user
  1885. 0, m_pwszAppDataDir)))
  1886. {
  1887. _TRACE(TRACE_DEBUGGING, "Error: Reading APPDATA path -- 0x%1x\n", GetLastError());
  1888. result = false;
  1889. }
  1890. if(!RevertToSelf())
  1891. {
  1892. LogFormattedGetLastError(EVENTLOG_ERROR_TYPE, TELNET_MSG_REVERTSELFFAIL, GetLastError());
  1893. result = false;
  1894. _TRACE(TRACE_DEBUGGING, "Error: RevertToSelf() -- 0x%1x", GetLastError());
  1895. }
  1896. }
  1897. }
  1898. Done:
  1899. if(profile.lpUserName)
  1900. delete[] profile.lpUserName;
  1901. if(profile.lpServerName)
  1902. delete[] profile.lpServerName;
  1903. if(profile.lpDefaultPath)
  1904. delete[] profile.lpDefaultPath;
  1905. if(profile.lpProfilePath)
  1906. delete[] profile.lpProfilePath;
  1907. if(lpWideDomain)
  1908. delete[] lpWideDomain;
  1909. return result;
  1910. }
  1911. bool
  1912. CShell::CancelNetConnections ( )
  1913. {
  1914. DWORD dwRetVal;
  1915. if (NULL == m_pSession->CSession::m_hToken)
  1916. {
  1917. // Nothing to do here, perhaps the session was quit in an unauthenticated state
  1918. // or authentication failed
  1919. return true;
  1920. }
  1921. _chVERIFY2( dwRetVal = ImpersonateLoggedOnUser(
  1922. m_pSession->CSession::m_hToken ) );
  1923. if( !dwRetVal )
  1924. {
  1925. return ( false );
  1926. }
  1927. DWORD dwResult;
  1928. HANDLE hEnum;
  1929. DWORD cbBuffer = 16384;
  1930. DWORD cEntries = 0xFFFFFFFF;
  1931. LPNETRESOURCE lpnrDrv;
  1932. DWORD i;
  1933. dwResult = WNetOpenEnum( RESOURCE_CONNECTED, RESOURCETYPE_ANY, 0, NULL,
  1934. &hEnum );
  1935. if(dwResult != NO_ERROR)
  1936. {
  1937. _TRACE( TRACE_DEBUGGING, "\nCannot enumerate network drives.\n" );
  1938. if(! RevertToSelf( ) )
  1939. {
  1940. LogFormattedGetLastError(EVENTLOG_ERROR_TYPE, TELNET_MSG_REVERTSELFFAIL, GetLastError());
  1941. }
  1942. return ( false );
  1943. }
  1944. do{
  1945. lpnrDrv = (LPNETRESOURCE) GlobalAlloc( GPTR, cbBuffer );
  1946. if( !lpnrDrv )
  1947. {
  1948. if(! RevertToSelf( ) )
  1949. {
  1950. LogFormattedGetLastError(EVENTLOG_ERROR_TYPE, TELNET_MSG_REVERTSELFFAIL, GetLastError());
  1951. }
  1952. return( false );
  1953. }
  1954. dwResult = WNetEnumResource( hEnum, &cEntries, lpnrDrv, &cbBuffer );
  1955. if (dwResult == NO_ERROR)
  1956. {
  1957. for( i = 0; i < cEntries; i++ )
  1958. {
  1959. if( lpnrDrv[i].lpLocalName != NULL )
  1960. {
  1961. //printf( "%s\t%s\n", lpnrDrv[i].lpLocalName,
  1962. // lpnrDrv[i].lpRemoteName );
  1963. WNetCancelConnection2( lpnrDrv[i].lpLocalName,
  1964. CONNECT_UPDATE_PROFILE, FALSE );
  1965. }
  1966. }
  1967. }
  1968. else if( dwResult != ERROR_NO_MORE_ITEMS )
  1969. {
  1970. _TRACE( TRACE_DEBUGGING, "Cannot complete network drive enumeration" );
  1971. GlobalFree( (HGLOBAL) lpnrDrv );
  1972. break;
  1973. }
  1974. GlobalFree( (HGLOBAL) lpnrDrv );
  1975. } while( dwResult != ERROR_NO_MORE_ITEMS );
  1976. WNetCloseEnum(hEnum);
  1977. if(! RevertToSelf( ) )
  1978. {
  1979. LogFormattedGetLastError(EVENTLOG_ERROR_TYPE, TELNET_MSG_REVERTSELFFAIL, GetLastError());
  1980. return( false );
  1981. }
  1982. return ( true );
  1983. }
  1984. void
  1985. CShell::Shutdown ( )
  1986. {
  1987. _TRACE( TRACE_DEBUGGING, "0x%p CTelnetClient::Shutdown() \n", this );
  1988. if(g_hProv)
  1989. {
  1990. CryptReleaseContext(g_hProv,0);
  1991. g_hProv = NULL;
  1992. }
  1993. if( !CancelNetConnections())
  1994. {
  1995. _TRACE( TRACE_DEBUGGING, "Error: CancelNetConnections()" );
  1996. }
  1997. //expect a exception in debug builds.
  1998. //cmd is killed by now in general case.
  1999. //This should be before cleanup. Otherwise this is an open handle to cmd.
  2000. if ((m_hProcess != INVALID_HANDLE_VALUE) && (m_hProcess != NULL))
  2001. {
  2002. TerminateProcess(m_hProcess, 0); // Don't care whether it succeeded or not.
  2003. TELNET_CLOSE_HANDLE( m_hProcess );
  2004. }
  2005. if ((m_hTempProcess != INVALID_HANDLE_VALUE) && (m_hTempProcess != NULL))
  2006. {
  2007. TerminateProcess(m_hTempProcess , 0); // Don't care whether it succeeded or not.
  2008. TELNET_CLOSE_HANDLE( m_hTempProcess );
  2009. }
  2010. LUID id = m_pSession->CSession::m_AuthenticationId;
  2011. //clean up potentially abandoned proceses
  2012. //this slows down the thread a lot
  2013. if( ( id.HighPart !=0 ) || ( id.LowPart != 0 ) )
  2014. KillProcs( id );
  2015. if( fnP_UnloadUserProfile && m_hCurrUserKey )
  2016. {
  2017. if( !fnP_UnloadUserProfile(m_pSession->CSession::m_hToken, m_hCurrUserKey) )
  2018. {
  2019. _TRACE( TRACE_DEBUGGING, "Error: UnloadUserProfile() - %1x", GetLastError() );
  2020. }
  2021. }
  2022. if(m_lpEnv)
  2023. delete[] ( UCHAR * )m_lpEnv;
  2024. m_lpEnv = NULL;
  2025. FreeConsole();
  2026. }
  2027. void
  2028. CShell::LoadLibNGetProc( )
  2029. {
  2030. CHAR szDllPath[MAX_PATH*2] = { 0 };
  2031. UINT iRet = 0;
  2032. //Dynamicallly load userenv.lib
  2033. iRet = GetSystemDirectoryA(szDllPath,(MAX_PATH*2)-1);
  2034. if(iRet == 0 || iRet >= (MAX_PATH*2))
  2035. {
  2036. goto End;
  2037. }
  2038. strncpy(szDllPath+iRet,"\\userenv.dll",(MAX_PATH*2)-iRet-1);
  2039. _chVERIFY2( hUserEnvLib = LoadLibraryA( szDllPath ) );
  2040. if( hUserEnvLib )
  2041. {
  2042. _chVERIFY2( fnP_LoadUserProfile = ( LOADUSERPROFILE * ) GetProcAddress
  2043. ( hUserEnvLib, "LoadUserProfileW" ) );
  2044. _chVERIFY2( fnP_UnloadUserProfile = ( UNLOADUSERPROFILE * )
  2045. GetProcAddress ( hUserEnvLib, "UnloadUserProfile" ) );
  2046. _chVERIFY2( fnP_CreateEnvironmentBlock = ( CREATEENVIRONMENTBLOCK * )
  2047. GetProcAddress( hUserEnvLib, "CreateEnvironmentBlock" ) );
  2048. _chVERIFY2( fnP_DestroyEnvironmentBlock = ( DESTROYENVIRONMENTBLOCK *)
  2049. GetProcAddress( hUserEnvLib, "DestroyEnvironmentBlock" ) );
  2050. _chVERIFY2( fnP_GetUserProfileDirectory = ( GETUSERPROFILEDIRECTORY * )
  2051. GetProcAddress( hUserEnvLib, "GetUserProfileDirectoryW" ) );
  2052. _chVERIFY2( fnP_GetDefaultUserProfileDirectory =
  2053. ( GETDEFAULTUSERPROFILEDIRECTORY * )
  2054. GetProcAddress( hUserEnvLib, "GetDefaultUserProfileDirectoryW" ));
  2055. }
  2056. End:
  2057. return;
  2058. }
  2059. void CopyRestOfEnv( LPTSTR *lpSrcEnv, LPTSTR *lpDstEnv )
  2060. {
  2061. DWORD dwEnvSize = 0;
  2062. LPTSTR lpTmp = *lpSrcEnv;
  2063. DWORD dwStringLen = 0;
  2064. while( *( *lpSrcEnv ) )
  2065. {
  2066. dwStringLen = ( wcslen( *lpSrcEnv ) + 1 );
  2067. dwEnvSize += dwStringLen;
  2068. *lpSrcEnv += dwStringLen;
  2069. }
  2070. //Copy L'\0' at the end of the block also
  2071. memcpy( *lpDstEnv, lpTmp, (dwEnvSize+1 )*2 ); // NO size info for Dest, Attack ? - Baskar
  2072. }
  2073. void PutStringInEnv( LPTSTR lpStr, LPTSTR *lpSrcEnv, LPTSTR *lpDstEnv, bool bOverwrite)
  2074. {
  2075. DWORD dwEnvSize = 0;
  2076. LPTSTR lpTmp = *lpSrcEnv;
  2077. DWORD dwStringLen = 0;
  2078. LPTSTR lpSrcTmp = NULL;
  2079. wchar_t *wcCharPos = NULL;
  2080. wchar_t *wcCharPosSrc = NULL;
  2081. bool bCopyString = true;
  2082. int nOffset, nOffsetSrc,nOffsetTemp;
  2083. wcCharPos = wcschr(lpStr, L'=');
  2084. if (NULL == wcCharPos)
  2085. {
  2086. _TRACE(TRACE_DEBUGGING, "Error: TLNTSESS: The syntax of an env string is VAR=VALUE\n");
  2087. return;
  2088. }
  2089. nOffset = (int)(wcCharPos - lpStr);
  2090. wcCharPosSrc = wcschr(*lpSrcEnv, L'=');
  2091. if (NULL == wcCharPos)
  2092. {
  2093. _TRACE(TRACE_DEBUGGING, "Error: TLNTSESS: The syntax of an env string is VAR=VALUE\n");
  2094. return;
  2095. }
  2096. nOffsetTemp = (int)(wcCharPosSrc - (*lpSrcEnv));
  2097. nOffsetSrc = max(nOffset,nOffsetTemp);
  2098. while(*(*lpSrcEnv) && _wcsnicmp(*lpSrcEnv, lpStr, nOffsetSrc) < 0)
  2099. {
  2100. dwStringLen = wcslen(*lpSrcEnv) + 1;
  2101. dwEnvSize += dwStringLen;
  2102. *lpSrcEnv += dwStringLen;
  2103. wcCharPosSrc = wcschr(*lpSrcEnv, L'=');
  2104. if (NULL == wcCharPosSrc)
  2105. {
  2106. _TRACE(TRACE_DEBUGGING, "Error: TLNTSESS: The syntax of an env string is VAR=VALUE\n");
  2107. return;
  2108. }
  2109. nOffsetTemp = (int)(wcCharPosSrc - (*lpSrcEnv));
  2110. nOffsetSrc = max(nOffset,nOffsetTemp);
  2111. }
  2112. if (*(*lpSrcEnv) )
  2113. {
  2114. int iRet = -1;
  2115. iRet = _wcsnicmp(*lpSrcEnv, lpStr, nOffsetSrc);
  2116. if(iRet == 0)
  2117. {
  2118. dwStringLen = wcslen(*lpSrcEnv) + 1;
  2119. *lpSrcEnv += dwStringLen;
  2120. if (!bOverwrite)
  2121. {
  2122. dwEnvSize += dwStringLen; // Copy this env variable too, so offset the size
  2123. bCopyString = false; // Because we found a match and we shouldn't overwrite
  2124. }
  2125. }
  2126. }
  2127. memcpy( *lpDstEnv, lpTmp, dwEnvSize*2 ); // No size info ? - Baskar
  2128. *lpDstEnv += dwEnvSize;
  2129. if (!bCopyString)
  2130. {
  2131. return;
  2132. }
  2133. dwStringLen = wcslen ( lpStr ) + 1 ;
  2134. memcpy( *lpDstEnv, lpStr, dwStringLen*2 ); // No size info ? - Baskar
  2135. *lpDstEnv += dwStringLen;
  2136. }
  2137. //This will break an absolute path into drive and relative path.
  2138. //Relative path is returned through szHomePath
  2139. void GetRelativePath( LPWSTR *szHomePath )
  2140. {
  2141. _chASSERT( szHomePath );
  2142. _chASSERT( *szHomePath );
  2143. while( *( *szHomePath ) != L'\0' && *( *szHomePath ) != L':' )
  2144. {
  2145. ( *szHomePath) ++;
  2146. }
  2147. if( *( *szHomePath ) == L':' )
  2148. {
  2149. ( *szHomePath) ++;
  2150. }
  2151. *( *szHomePath ) = L'\0';
  2152. ( *szHomePath)++;
  2153. }
  2154. //It returns the size in terms of WCHARS
  2155. void FindSizeOfEnvBlock( DWORD *dwEnvSize, LPVOID lpTmpEnv )
  2156. {
  2157. _chASSERT( dwEnvSize );
  2158. _chASSERT( lpTmpEnv );
  2159. //The Environment block has set of strings and ends with L'\0'
  2160. while( ( *( ( UCHAR * )lpTmpEnv ) ) )
  2161. {
  2162. DWORD dwStringLen = wcslen( ( LPTSTR )lpTmpEnv ) + 1;
  2163. *dwEnvSize += dwStringLen ;
  2164. lpTmpEnv = ( TCHAR * )lpTmpEnv + dwStringLen;
  2165. }
  2166. *dwEnvSize += 1; //Accounting for L'\0' at the end of block
  2167. }
  2168. // do this so that the cmd.exe
  2169. // gets the environment with following variables set
  2170. void
  2171. CShell::ExportEnvVariables()
  2172. {
  2173. TCHAR szHomeDirectoryPath[ MAX_PATH + 1 ];
  2174. TCHAR *szHomePath = NULL;
  2175. LPVOID lpTmpEnv = NULL;
  2176. LPVOID lpTmpOldEnv = NULL;
  2177. LPVOID lpNewEnv = NULL;
  2178. DWORD dwEnvSize = 0;
  2179. TCHAR szTmp[] = L"\\";
  2180. DWORD dwIndex = 0;
  2181. if(m_lpEnv == NULL)
  2182. return;
  2183. wcsncpy( szHomeDirectoryPath, wideHomeDir , MAX_PATH);
  2184. szHomePath = szHomeDirectoryPath;
  2185. GetRelativePath( &szHomePath );
  2186. TCHAR szHomeVar[ MAX_PATH + UNICODE_STR_SIZE(ENV_HOMEPATH) ] = { 0 };
  2187. TCHAR szHomeDirVar[ MAX_PATH + 1]= { 0 };
  2188. TCHAR szTermVar[ MAX_PATH + 1 ]= { 0 };
  2189. TCHAR szAppDataDirVar[MAX_PATH + UNICODE_STR_SIZE(ENV_APPDATA)]= { 0 };
  2190. TCHAR szUserName[MAX_PATH+1+ UNICODE_STR_SIZE(ENV_USERNAME)]= { 0 };
  2191. LPWSTR szUserDomain = NULL;
  2192. DWORD domainsize = wcslen(m_pSession->CSession::m_szDomain) +1 +UNICODE_STR_SIZE(ENV_USERDOMAIN);
  2193. LPWSTR szUserProfile = NULL;
  2194. DWORD profilesize = wcslen(pProfilePath)+1+UNICODE_STR_SIZE(ENV_USERPROFILE);
  2195. LPWSTR pszUserName = NULL;
  2196. TCHAR *szTempTerm = NULL;
  2197. TCHAR *szTerm = NULL;
  2198. szUserDomain = new WCHAR[domainsize];
  2199. if(szUserDomain == NULL)
  2200. {
  2201. lpTmpOldEnv = m_lpEnv;
  2202. m_lpEnv = NULL;
  2203. goto ExitOnError;
  2204. }
  2205. szUserProfile = new WCHAR[profilesize];
  2206. if(szUserProfile == NULL)
  2207. {
  2208. lpTmpOldEnv = m_lpEnv;
  2209. m_lpEnv = NULL;
  2210. goto ExitOnError;
  2211. }
  2212. wcscpy( szHomeVar, ENV_HOMEPATH );
  2213. wcscpy( szHomeDirVar, ENV_HOMEDRIVE );
  2214. wcscpy( szTermVar, ENV_TERM );
  2215. wcscpy( szAppDataDirVar, ENV_APPDATA );
  2216. wcscpy(szUserName, ENV_USERNAME);
  2217. wcscpy(szUserDomain, ENV_USERDOMAIN);
  2218. wcscpy(szUserProfile, ENV_USERPROFILE);
  2219. if(!ConvertSChartoWChar( m_pSession->CSession::m_pszTermType, &szTerm ))
  2220. {
  2221. lpTmpOldEnv = m_lpEnv;
  2222. m_lpEnv = NULL;
  2223. goto ExitOnError;
  2224. }
  2225. // Convert term type to lower case, so that UNIX programs can work...
  2226. for( szTempTerm = szTerm; *szTempTerm; szTempTerm++)
  2227. {
  2228. *szTempTerm = towlower(*szTempTerm);
  2229. }
  2230. while( ( dwIndex < MAX_PATH + 1 ) && szHomePath[ dwIndex ] )
  2231. {
  2232. if( szHomePath[ dwIndex ] == L'\\' || szHomePath[ dwIndex ] == L'/' )
  2233. {
  2234. szTmp[0] = szHomePath[ dwIndex ];
  2235. break;
  2236. }
  2237. dwIndex++;
  2238. }
  2239. if(!ConvertSChartoWChar(m_pSession->CSession::m_pszUserName, &pszUserName))
  2240. {
  2241. lpTmpOldEnv = m_lpEnv;
  2242. m_lpEnv = NULL;
  2243. goto ExitOnError;
  2244. }
  2245. wcsncat( szHomeVar, szTmp, 1 );
  2246. wcsncat( szHomeVar, szHomePath, MAX_PATH );
  2247. wcsncat( szHomeDirVar, szHomeDirectoryPath, MAX_PATH );
  2248. wcsncat( szTermVar, szTerm, MAX_PATH );
  2249. wcsncat( szAppDataDirVar, m_pwszAppDataDir, MAX_PATH );
  2250. wcsncat( szUserName, pszUserName, MAX_PATH);
  2251. wcsncat( szUserDomain,m_pSession->CSession::m_szDomain,domainsize -1);
  2252. wcsncat( szUserProfile,pProfilePath, profilesize -1);
  2253. szUserDomain[domainsize -1] = L'\0';
  2254. szUserProfile[profilesize -1] = L'\0';
  2255. FindSizeOfEnvBlock( &dwEnvSize, m_lpEnv );
  2256. dwEnvSize += ( wcslen( szHomeVar ) + 2 );
  2257. dwEnvSize += ( wcslen( szHomeDirVar ) + 2 );
  2258. dwEnvSize += ( wcslen( szTermVar ) + 2 );
  2259. dwEnvSize += ( wcslen( szAppDataDirVar ) + 2 );
  2260. dwEnvSize += ( wcslen( szUserName ) + 2 );
  2261. dwEnvSize += ( wcslen( szUserDomain ) + 2 );
  2262. dwEnvSize += ( wcslen( szUserProfile ) + 2 );
  2263. lpTmpEnv = m_lpEnv;
  2264. lpTmpOldEnv = m_lpEnv;
  2265. m_lpEnv = ( VOID * ) new UCHAR[ dwEnvSize * 2 ];
  2266. if( !m_lpEnv )
  2267. {
  2268. goto ExitOnError;
  2269. }
  2270. lpNewEnv = m_lpEnv;
  2271. /*
  2272. * Make calls to PutStringInEnv alphabetically. This function moves the lpTmpEnv
  2273. * variable and only searches forward. So if the calls aren't alphabetical, then
  2274. * you wouldn't find a match even if there is one
  2275. */
  2276. PutStringInEnv( szAppDataDirVar, (LPTSTR *)&lpTmpEnv, ( LPTSTR * )&lpNewEnv, false);
  2277. PutStringInEnv( szHomeDirVar, ( LPTSTR * )&lpTmpEnv, ( LPTSTR * )&lpNewEnv, false);
  2278. PutStringInEnv( szHomeVar, ( LPTSTR * )&lpTmpEnv, ( LPTSTR * )&lpNewEnv, false);
  2279. PutStringInEnv( szTermVar, ( LPTSTR * )&lpTmpEnv, ( LPTSTR * )&lpNewEnv, true);
  2280. PutStringInEnv( szUserDomain, ( LPTSTR * )&lpTmpEnv, ( LPTSTR * )&lpNewEnv, true);
  2281. PutStringInEnv( szUserName, ( LPTSTR * )&lpTmpEnv, ( LPTSTR * )&lpNewEnv, true);
  2282. PutStringInEnv( szUserProfile, ( LPTSTR * )&lpTmpEnv, ( LPTSTR * )&lpNewEnv, true);
  2283. CopyRestOfEnv( ( LPTSTR * )&lpTmpEnv, ( LPTSTR * )&lpNewEnv );
  2284. ExitOnError:
  2285. delete[] szTerm;
  2286. if(pszUserName)
  2287. delete [] pszUserName;
  2288. if(szUserDomain)
  2289. delete [] szUserDomain;
  2290. if(szUserProfile)
  2291. delete [] szUserProfile;
  2292. if( fnP_DestroyEnvironmentBlock )
  2293. {
  2294. fnP_DestroyEnvironmentBlock( lpTmpOldEnv );
  2295. }
  2296. }
  2297. //Load the profile path for setting in the environment variable. Currently
  2298. //Telnet session exports APPDATA, HOMEDRIVE, HOMEPATH, USERNAME,
  2299. //USERDOMAIN,USERPROFILE env variables to the newly created cmd.exe
  2300. //If any more environment variables need to be exported, corresponding
  2301. //Global variables should be loaded in this function.
  2302. void
  2303. CShell::GetEnvVarData()
  2304. {
  2305. BOOL fnResult = FALSE;
  2306. LPTSTR szProfilePath = NULL;
  2307. DWORD userPathsize = MAX_PATH +1;
  2308. do
  2309. {
  2310. szProfilePath = new TCHAR[ userPathsize ];
  2311. if( !szProfilePath )
  2312. {
  2313. break;
  2314. }
  2315. if( !fnP_GetUserProfileDirectory )
  2316. {
  2317. break;
  2318. }
  2319. fnResult = fnP_GetUserProfileDirectory ( m_pSession->CSession::m_hToken,
  2320. szProfilePath, &userPathsize);
  2321. if (!fnResult)
  2322. {
  2323. DWORD err;
  2324. if ( ( err = GetLastError() ) != ERROR_INSUFFICIENT_BUFFER )
  2325. {
  2326. fnResult = TRUE;
  2327. _TRACE( TRACE_DEBUGGING, "Error: GetUserProfileDirecto"
  2328. "ry() -- 0x%1x", err );
  2329. }
  2330. delete[] szProfilePath;
  2331. szProfilePath = NULL;
  2332. }
  2333. else
  2334. {
  2335. if(pProfilePath)
  2336. {
  2337. delete [] pProfilePath;
  2338. }
  2339. AllocNCpyWStr(&pProfilePath, szProfilePath);
  2340. }
  2341. } while ( !fnResult );
  2342. if(szProfilePath)
  2343. delete [] szProfilePath;
  2344. }
  2345. //This is only on NT4 where there is no LoadUserProfile()
  2346. void
  2347. CShell::SetEnvVariables()
  2348. {
  2349. TCHAR szHomeDirectoryPath[ MAX_PATH + 1 ] = { 0 };
  2350. TCHAR *szHomePath = NULL;
  2351. UINT_PTR space_left;
  2352. DWORD dwIndex = 0;
  2353. WCHAR szTmp[] = L"\\";
  2354. TCHAR szHomeVar[ MAX_PATH + UNICODE_STR_SIZE(ENV_HOMEPATH) ] = { 0 };
  2355. TCHAR szHomeDirVar[ MAX_PATH + 1]= { 0 };
  2356. wcsncpy( szHomeDirectoryPath, wideHomeDir, MAX_PATH );
  2357. szHomePath = szHomeDirectoryPath;
  2358. GetRelativePath( &szHomePath );
  2359. _chVERIFY2( SetEnvironmentVariableW( L"HOMEDRIVE", szHomeDirectoryPath ) );
  2360. while( ( dwIndex < MAX_PATH + 1 ) && szHomePath[ dwIndex ] )
  2361. {
  2362. if( szHomePath[ dwIndex ] == L'\\' || szHomePath[ dwIndex ] == L'/' )
  2363. {
  2364. szTmp[0] = szHomePath[ dwIndex ];
  2365. break;
  2366. }
  2367. dwIndex++;
  2368. }
  2369. wcsncat( szHomeVar, szTmp, 1 );
  2370. space_left = MAX_PATH - (szHomePath - szHomeDirectoryPath);
  2371. wcsncat( szHomePath, L"\\", space_left );
  2372. wcsncat( szHomeVar, szHomePath, MAX_PATH );
  2373. _chVERIFY2( SetEnvironmentVariableW( L"HOMEPATH", szHomeVar ) );
  2374. _chVERIFY2( SetEnvironmentVariableA( "TERM", m_pSession->CSession::m_pszTermType ) );
  2375. SetEnvironmentVariableA("USERNAME",m_pSession->CSession::m_pszUserName);
  2376. SetEnvironmentVariableW(L"USERPROFILE",pProfilePath);
  2377. SetEnvironmentVariableW(L"USERDOMAIN",m_pSession->CSession::m_szDomain);
  2378. }
  2379. #ifdef ENABLE_LOGON_SCRIPT
  2380. BOOL
  2381. CShell::InjectUserScriptPathIntoPath( TCHAR szUserScriptPath[] )
  2382. {
  2383. DWORD dwSize = 0;
  2384. TCHAR *szNewPath = NULL;
  2385. DWORD dwRetVal = 0;
  2386. BOOL bRetVal = FALSE;
  2387. if (NULL == szUserScriptPath )
  2388. {
  2389. bRetVal = TRUE;
  2390. goto ExitOnError;
  2391. }
  2392. if( wcslen( szUserScriptPath ) == 0 )
  2393. {
  2394. bRetVal = TRUE;
  2395. goto ExitOnError;
  2396. }
  2397. if( m_lpEnv )
  2398. {
  2399. DWORD dwEnvSize = 0;
  2400. LPVOID lpTmpOldEnv = NULL;
  2401. LPVOID lpTmpEnv = NULL;
  2402. TCHAR *szVar = NULL;
  2403. FindSizeOfEnvBlock( &dwEnvSize, m_lpEnv );
  2404. dwSize = ( wcslen( szUserScriptPath ) + wcslen( L";" ) + 1);
  2405. lpTmpEnv = ( VOID * ) new TCHAR[ ( dwEnvSize + dwSize ) ];
  2406. if( lpTmpEnv )
  2407. {
  2408. bool bEndSearch = false;
  2409. lpTmpOldEnv = m_lpEnv;
  2410. memcpy( lpTmpEnv, m_lpEnv, dwEnvSize * sizeof(TCHAR) );
  2411. szVar = ( TCHAR * )lpTmpEnv;
  2412. m_lpEnv = lpTmpEnv;
  2413. do
  2414. {
  2415. if( _tcsnicmp( szVar, L"PATH=", LENGTH_OF_PATH_EQUALS ) == 0 )
  2416. {
  2417. TCHAR *szVarNextToPath = NULL;
  2418. bEndSearch = true;
  2419. szVarNextToPath = szVar + wcslen( szVar ) + 1; //points to variable next to path
  2420. szVar += LENGTH_OF_PATH_EQUALS; //Move past PATH=
  2421. wcscat( szVar, L";" );
  2422. wcscat( szVar, szUserScriptPath );
  2423. szVar += ( wcslen( szVar ) + 1 ); //Move past value of path
  2424. DWORD dwOffset = (DWORD)( szVarNextToPath - ( TCHAR *)m_lpEnv );
  2425. //copy restof the env block
  2426. memcpy( szVar, (( ( TCHAR * )lpTmpOldEnv )+ dwOffset) , (dwEnvSize*sizeof(szVar[0]) - dwOffset) );
  2427. break; //we are done with our job.
  2428. }
  2429. szVar = wcschr( ( TCHAR * )lpTmpEnv, L'\0' ) ; //look for L'\0'
  2430. if( szVar )
  2431. {
  2432. szVar++; //move past L'\0'
  2433. }
  2434. else
  2435. {
  2436. //Should not happen
  2437. _chASSERT( 0 );
  2438. break;
  2439. }
  2440. lpTmpEnv = szVar;
  2441. }
  2442. while( *szVar != L'\0' );
  2443. delete[] ( ( UCHAR * )lpTmpOldEnv );
  2444. }
  2445. }
  2446. else
  2447. {
  2448. dwSize = GetEnvironmentVariable( L"PATH", NULL, 0 );
  2449. dwSize += ( wcslen( szUserScriptPath ) + wcslen( L";" ) ); //find future length of path
  2450. szNewPath = new TCHAR[ dwSize + 1 ];
  2451. if( szNewPath )
  2452. {
  2453. dwRetVal = GetEnvironmentVariable( L"PATH", szNewPath, dwSize );
  2454. if(dwRetVal == 0 || dwRetVal > dwSize )
  2455. goto ExitOnError;
  2456. wcscat( szNewPath, L";" );
  2457. wcscat( szNewPath, szUserScriptPath );
  2458. if(!SetEnvironmentVariable( L"PATH", szNewPath ) )
  2459. goto ExitOnError;
  2460. }
  2461. else
  2462. {
  2463. goto ExitOnError;
  2464. }
  2465. }
  2466. bRetVal = TRUE;
  2467. ExitOnError:
  2468. if(szNewPath)
  2469. {
  2470. delete[] szNewPath;
  2471. }
  2472. return(bRetVal);
  2473. }
  2474. #endif