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.

1676 lines
46 KiB

  1. //Copyright (c) Microsoft Corporation. All rights reserved.
  2. #include <CmnHdr.h>
  3. #include <nt.h>
  4. #include <ntrtl.h>
  5. #include <nturtl.h>
  6. #include <ntlsa.h>
  7. #include <windows.h>
  8. #include <TChar.h>
  9. #include <MsgFile.h>
  10. #include <TelnetD.h>
  11. #include <debug.h>
  12. #include <Regutil.h>
  13. #include <Ipc.h>
  14. #include <TlntUtils.h>
  15. #include <stdlib.h>
  16. #include <wincrypt.h>
  17. #pragma warning( disable: 4127 )
  18. #pragma warning( disable: 4706 )
  19. using namespace _Utils;
  20. using CDebugLevel::TRACE_DEBUGGING;
  21. using CDebugLevel::TRACE_HANDLE;
  22. using CDebugLevel::TRACE_SOCKET;
  23. HANDLE g_hSyncCloseHandle;
  24. HCRYPTPROV g_hProv = { 0 };
  25. PSID administratorsSid = NULL,
  26. everyoneSid = NULL,
  27. localSystemSid = NULL,
  28. localLocalSid = NULL,
  29. localNetworkSid = NULL;
  30. void *SfuZeroMemory(
  31. void *ptr,
  32. unsigned int cnt
  33. )
  34. {
  35. volatile char *vptr = (volatile char *)ptr;
  36. while (cnt)
  37. {
  38. *vptr = 0;
  39. vptr ++;
  40. cnt --;
  41. }
  42. return ptr;
  43. }
  44. bool IsThisMachineDC()
  45. {
  46. bool bRetVal = false;
  47. HKEY hkey = NULL;
  48. DWORD dwRetVal = 0;
  49. LPWSTR pszProductType = NULL;
  50. //
  51. // Query the registry for the product type.
  52. //
  53. dwRetVal = RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_PRODUCT_OPTION,
  54. 0, KEY_READ, &hkey);
  55. if(dwRetVal != ERROR_SUCCESS )
  56. {
  57. _TRACE( TRACE_DEBUGGING, "Error: RegOpenKeyEx() -- 0x%1x", dwRetVal);
  58. bRetVal = false;
  59. goto IsThisMachineDCAbort;
  60. }
  61. if( !GetRegistryString( hkey, NULL, L"ProductType", &pszProductType, L"",FALSE ) )
  62. {
  63. bRetVal = false;
  64. goto IsThisMachineDCAbort;
  65. }
  66. if( _wcsicmp( pszProductType, L"LanManNT" ) == 0 )
  67. {
  68. bRetVal = true;
  69. }
  70. IsThisMachineDCAbort:
  71. delete[] pszProductType;
  72. if(hkey)
  73. {
  74. RegCloseKey (hkey);
  75. }
  76. return bRetVal;
  77. }
  78. //Before we proceed any further check whether we are hosting the domain
  79. bool GetDomainHostedByThisMc( LPWSTR szDomain )
  80. {
  81. OBJECT_ATTRIBUTES obj_attr = { 0 };
  82. LSA_HANDLE policy;
  83. bool bRetVal = false;
  84. NTSTATUS nStatus = STATUS_SUCCESS;
  85. _chASSERT( szDomain );
  86. if( !szDomain )
  87. {
  88. goto GetDomainHostedByThisMcAbort;
  89. }
  90. obj_attr.Length = sizeof(obj_attr);
  91. szDomain[0] = L'\0';
  92. nStatus = LsaOpenPolicy(
  93. NULL, // Local machine
  94. &obj_attr,
  95. POLICY_VIEW_LOCAL_INFORMATION,
  96. &policy
  97. );
  98. if (NT_SUCCESS(nStatus))
  99. {
  100. POLICY_ACCOUNT_DOMAIN_INFO *info = NULL;
  101. nStatus = LsaQueryInformationPolicy(
  102. policy,
  103. PolicyAccountDomainInformation,
  104. (PVOID *)&info
  105. );
  106. if (NT_SUCCESS(nStatus))
  107. {
  108. bRetVal = true;
  109. wcscpy( szDomain, info->DomainName.Buffer );
  110. LsaFreeMemory(info);
  111. }
  112. LsaClose(policy);
  113. }
  114. GetDomainHostedByThisMcAbort:
  115. return bRetVal;
  116. }
  117. bool GetRegistryDW( HKEY hkKeyHandle1, HKEY hkKeyHandle2, LPTSTR szKeyName,
  118. DWORD *pdwVariable, DWORD dwDefaultVal, BOOL fOverwrite )
  119. {
  120. if( !szKeyName || !pdwVariable )
  121. {
  122. _chASSERT( 0 );
  123. return false;
  124. }
  125. if( hkKeyHandle1 )
  126. {
  127. if( !GetRegistryDWORD( hkKeyHandle1, szKeyName, pdwVariable, dwDefaultVal, fOverwrite ) )
  128. {
  129. RegCloseKey( hkKeyHandle1 );
  130. LogEvent( EVENTLOG_ERROR_TYPE, MSG_REGISTRYKEY, szKeyName );
  131. return ( false );
  132. }
  133. }
  134. if( hkKeyHandle2 != NULL )
  135. {
  136. if( !GetRegistryDWORD( hkKeyHandle2, szKeyName, pdwVariable, dwDefaultVal, fOverwrite ) )
  137. {
  138. RegCloseKey( hkKeyHandle2 );
  139. LogEvent( EVENTLOG_ERROR_TYPE, MSG_REGISTRYKEY, szKeyName );
  140. return ( false );
  141. }
  142. }
  143. return( true );
  144. }
  145. bool GetRegistryString( HKEY hkKeyHandle1, HKEY hkKeyHandle2, LPTSTR szKeyName,
  146. LPTSTR *pszVariable, LPTSTR szDefaultVal, BOOL fOverwrite )
  147. {
  148. if( !pszVariable || !szKeyName || !szDefaultVal )
  149. {
  150. _chASSERT( 0 );
  151. return false;
  152. }
  153. *pszVariable = NULL;
  154. if( hkKeyHandle1 != NULL )
  155. {
  156. if( !GetRegistrySZ( hkKeyHandle1, szKeyName, pszVariable, szDefaultVal,fOverwrite ) )
  157. {
  158. RegCloseKey( hkKeyHandle1 );
  159. LogEvent( EVENTLOG_ERROR_TYPE, MSG_REGISTRYKEY, szKeyName );
  160. return ( false );
  161. }
  162. }
  163. if( hkKeyHandle2 != NULL )
  164. {
  165. delete[] *pszVariable;
  166. if( !GetRegistrySZ( hkKeyHandle2, szKeyName, pszVariable, szDefaultVal,fOverwrite ) )
  167. {
  168. RegCloseKey( hkKeyHandle2 );
  169. LogEvent( EVENTLOG_ERROR_TYPE, MSG_REGISTRYKEY, szKeyName );
  170. return ( false );
  171. }
  172. }
  173. return( *pszVariable != NULL );
  174. }
  175. //Allocates memory for the destination buffer and expands the environment strgs
  176. bool AllocateNExpandEnvStrings( LPWSTR strSrc, LPWSTR *strDst)
  177. {
  178. DWORD expectedSize = 1024;
  179. DWORD actualSize = 0;
  180. *strDst = NULL;
  181. if( !strSrc )
  182. {
  183. return false;
  184. }
  185. do
  186. {
  187. if ( actualSize > expectedSize )
  188. {
  189. delete[] ( *strDst );
  190. expectedSize = actualSize;
  191. }
  192. *strDst = new TCHAR[ expectedSize ];
  193. if( !( *strDst ) )
  194. {
  195. return false;
  196. }
  197. actualSize = ExpandEnvironmentStrings( strSrc, *strDst, expectedSize );
  198. if(!actualSize)
  199. {
  200. if(*strDst)
  201. {
  202. delete[] ( *strDst );
  203. }
  204. *strDst = NULL;
  205. return false;
  206. }
  207. }
  208. while( actualSize > expectedSize );
  209. return true;
  210. }
  211. /* If this Function returns true, lpWideCharStr
  212. has converted wide string. */
  213. bool ConvertSChartoWChar(char *pSChar, LPWSTR lpWideCharStr)
  214. {
  215. if( !pSChar )
  216. {
  217. return false;
  218. }
  219. //Convert the multibyte string to a wide-character string.
  220. if( !MultiByteToWideChar( GetConsoleCP(), 0, pSChar, -1, lpWideCharStr,
  221. MAX_STRING_LENGTH + 1 ) )
  222. {
  223. return false;
  224. }
  225. return true;
  226. }
  227. /* If this Function returns true, *lpWideCharStr is allocated memory and points
  228. to wide string. Otherwise it is NULL */
  229. bool ConvertSChartoWChar(char *pSChar, LPWSTR *lpWideCharStr)
  230. {
  231. int nLenOfWideCharStr;
  232. *lpWideCharStr = NULL;
  233. if( !pSChar )
  234. {
  235. return false;
  236. }
  237. nLenOfWideCharStr = strlen( pSChar ) + 1;
  238. *lpWideCharStr = new WCHAR[ nLenOfWideCharStr ];
  239. if( !(*lpWideCharStr) )
  240. {
  241. return false;
  242. }
  243. //Convert the multibyte string to a wide-character string.
  244. if( !MultiByteToWideChar( GetConsoleCP(), 0, pSChar, -1, *lpWideCharStr,
  245. nLenOfWideCharStr ) )
  246. {
  247. return false;
  248. }
  249. return true;
  250. }
  251. //Allocates and copies a WSTR
  252. bool AllocNCpyWStr(LPWSTR *strDest, LPWSTR strSrc )
  253. {
  254. DWORD wStrLen;
  255. if( !strSrc )
  256. {
  257. *strDest = NULL;
  258. return false;
  259. }
  260. wStrLen = wcslen( strSrc );
  261. *strDest = new WCHAR[ wStrLen + 1 ];
  262. if( *strDest )
  263. {
  264. wcscpy( *strDest, strSrc );//no attack. Dest string is allocated from the length of src string.
  265. return true;
  266. }
  267. return false;
  268. }
  269. bool WriteToPipe( HANDLE hWritingPipe, LPVOID lpData, DWORD dwSize,
  270. LPOVERLAPPED lpObj )
  271. {
  272. DWORD dwNum = 0;
  273. _chASSERT( hWritingPipe );
  274. if( hWritingPipe == INVALID_HANDLE_VALUE)
  275. {
  276. return false;
  277. }
  278. BOOL bRetVal = 0;
  279. bRetVal = WriteFile( hWritingPipe, lpData, dwSize, &dwNum, lpObj );
  280. if( bRetVal == 0 )
  281. {
  282. DWORD dwErr = 0;
  283. dwErr = GetLastError();
  284. if( dwErr != ERROR_IO_PENDING )
  285. {
  286. if( dwErr != ERROR_NO_DATA ) //we found this error to be not interesting. Fix for bug 6777
  287. {
  288. LogFormattedGetLastError( EVENTLOG_ERROR_TYPE, MSG_ERR_WRITEPIPE,
  289. dwErr );
  290. }
  291. _TRACE( TRACE_DEBUGGING, "WriteFile: 0x%1x", dwErr );
  292. goto ExitOnError;
  293. }
  294. else
  295. {
  296. bRetVal = 1;
  297. }
  298. }
  299. TlntSynchronizeOn(lpObj->hEvent);
  300. ExitOnError:
  301. return ( bRetVal != 0 );
  302. }
  303. bool WriteToPipe( HANDLE hWritingPipe, UCHAR ucMsgType, LPOVERLAPPED lpObj )
  304. {
  305. UCHAR *ucMsg = NULL;
  306. DWORD dwNum = 0;
  307. BOOL bRetVal = 0;
  308. _chASSERT( hWritingPipe );
  309. if( hWritingPipe == INVALID_HANDLE_VALUE )
  310. {
  311. goto ExitOnError;
  312. }
  313. ucMsg = new UCHAR[ IPC_HEADER_SIZE ];
  314. if( !ucMsg )
  315. {
  316. goto ExitOnError;
  317. }
  318. memcpy( ucMsg, &ucMsgType, sizeof( UCHAR ) );//no overflow. Size constant.
  319. SfuZeroMemory( ucMsg + 1, sizeof( DWORD ) );
  320. bRetVal = WriteToPipe( hWritingPipe, ucMsg, IPC_HEADER_SIZE, lpObj );
  321. delete[] ucMsg;
  322. ExitOnError:
  323. return ( bRetVal != 0 );
  324. }
  325. bool StuffEscapeIACs( UCHAR bufDest[], UCHAR *bufSrc, DWORD* pdwSize )
  326. {
  327. DWORD length;
  328. DWORD cursorDest = 0;
  329. DWORD cursorSrc = 0;
  330. bool found = false;
  331. //get the location of the first occurrence of TC_IAC
  332. PUCHAR pDest = (PUCHAR) memchr( bufSrc, TC_IAC, *pdwSize );//Attack ? Size not known.
  333. while( pDest != NULL )
  334. {
  335. //copy data upto and including that point
  336. //This should not be more than MAX DWORD because we scrape atmost one cmd at a time
  337. length = ( DWORD ) ( (pDest - ( bufSrc + cursorSrc)) + 1 );
  338. memcpy( bufDest + cursorDest, bufSrc + cursorSrc, length );//Attack ? Dest buffer size not known.
  339. cursorDest += length;
  340. //stuff another TC_IAC
  341. bufDest[ cursorDest++ ] = TC_IAC;
  342. cursorSrc += length;
  343. pDest = (PUCHAR) memchr( bufSrc + cursorSrc, TC_IAC,
  344. *pdwSize - cursorSrc );
  345. }
  346. //copy remaining data
  347. memcpy( bufDest + cursorDest, bufSrc + cursorSrc,
  348. *pdwSize - cursorSrc );//Attack? Dest buffer size not known
  349. if( cursorDest )
  350. {
  351. *pdwSize += cursorDest - cursorSrc;
  352. found = true;
  353. }
  354. return ( found );
  355. }
  356. void
  357. FillProcessStartupInfo( STARTUPINFO *si, HANDLE hStdinPipe, HANDLE hStdoutPipe,
  358. HANDLE hStdError, WCHAR *Desktop)
  359. {
  360. _chASSERT( si != NULL );
  361. SfuZeroMemory(si, sizeof(*si));
  362. si->cb = sizeof( STARTUPINFO );
  363. si->lpDesktop = Desktop;
  364. si->dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  365. si->hStdInput = hStdinPipe;
  366. si->hStdOutput = hStdoutPipe;
  367. si->hStdError = hStdError;
  368. si->wShowWindow = SW_HIDE;
  369. return;
  370. }
  371. void
  372. LogToTlntsvrLog( HANDLE hEventSource, WORD wType, DWORD dwEventID,
  373. LPCTSTR* pLogString )
  374. {
  375. _chASSERT( hEventSource );
  376. if( !hEventSource )
  377. {
  378. return;
  379. }
  380. // Write to event log.
  381. switch( wType) {
  382. case EVENTLOG_INFORMATION_TYPE :
  383. _chVERIFY2( ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0,
  384. dwEventID, NULL, 1, 0, pLogString, NULL) );
  385. break;
  386. case EVENTLOG_WARNING_TYPE :
  387. _chVERIFY2( ReportEvent(hEventSource, EVENTLOG_WARNING_TYPE, 0,
  388. dwEventID, NULL, 1, 0, pLogString, NULL) );
  389. break;
  390. case EVENTLOG_ERROR_TYPE :
  391. _chVERIFY2( ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0, dwEventID,
  392. NULL, 1, 0, pLogString, NULL) );
  393. break;
  394. case EVENTLOG_AUDIT_SUCCESS :
  395. _chVERIFY2( ReportEvent(hEventSource, EVENTLOG_AUDIT_SUCCESS, 0,
  396. dwEventID , NULL, 1, 0, pLogString, NULL) );
  397. break;
  398. case EVENTLOG_AUDIT_FAILURE :
  399. _chVERIFY2( ReportEvent(hEventSource, EVENTLOG_AUDIT_FAILURE, 0,
  400. dwEventID , NULL, 1, 0, pLogString, NULL) );
  401. break;
  402. default:
  403. break;
  404. }
  405. return;
  406. }
  407. void
  408. GetErrMsgString( DWORD dwErrNum, LPTSTR *lpBuffer )
  409. {
  410. DWORD dwStatus = 0;
  411. _chVERIFY2( dwStatus = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  412. FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErrNum, LANG_NEUTRAL,
  413. ( LPTSTR )lpBuffer, 0, NULL ) );
  414. if( !dwStatus )
  415. {
  416. if (lpBuffer)
  417. {
  418. *lpBuffer = (LPTSTR) LocalAlloc( LPTR, 2 );
  419. if (*lpBuffer)
  420. (*lpBuffer)[0] = _T('\0');
  421. }
  422. }
  423. return;
  424. }
  425. bool
  426. DecodeWSAErrorCodes( DWORD dwStatus, ... )
  427. {
  428. DWORD dwEventId;
  429. WCHAR szMsg[ 50 ]; //This string is just to hold a 32 bit number
  430. DWORD dwTelnetPort;
  431. va_list pArg;
  432. va_start(pArg, dwStatus);
  433. dwTelnetPort = va_arg(pArg, DWORD);
  434. va_end(pArg);
  435. switch( dwStatus )
  436. {
  437. case WSAEACCES:
  438. dwEventId = MSG_WSAPORTINUSE;
  439. break;
  440. case WSANOTINITIALISED:
  441. dwEventId = MSG_WSANOTINITIALISED;
  442. break;
  443. case WSAENETDOWN:
  444. dwEventId = MSG_WSAENETDOWN;
  445. break;
  446. case WSAENOBUFS:
  447. dwEventId = MSG_WSAENOBUFS;
  448. break;
  449. case WSAEHOSTUNREACH:
  450. dwEventId = MSG_WSAEHOSTUNREACH;
  451. break;
  452. case WSAECONNABORTED:
  453. dwEventId = MSG_WSAECONNABORTED;
  454. break;
  455. case WSAETIMEDOUT:
  456. dwEventId = MSG_WSAETIMEDOUT;
  457. break;
  458. default:
  459. // if (dwStatus == WSAENOTSOCK)
  460. // {
  461. // DebugBreak();
  462. // }
  463. dwEventId = MSG_WSAGETLASTERROR;
  464. break;
  465. }
  466. if( MSG_WSAGETLASTERROR == dwEventId )
  467. {
  468. //wsprintf( szMsg, L"%lu", dwStatus );
  469. LogFormattedGetLastError(EVENTLOG_ERROR_TYPE,MSG_WSAGETLASTERROR,dwStatus);
  470. }
  471. else if( MSG_WSAPORTINUSE == dwEventId )
  472. {
  473. _snwprintf( szMsg,(sizeof(szMsg)/sizeof(WCHAR)) - 1, L"%lu", dwTelnetPort );
  474. LogEvent( EVENTLOG_ERROR_TYPE, dwEventId, szMsg );
  475. }
  476. else
  477. {
  478. lstrcpyW( szMsg, L" " );//No overflow. Source string is const wchar *.
  479. LogEvent( EVENTLOG_ERROR_TYPE, dwEventId, szMsg );
  480. }
  481. _TRACE( TRACE_DEBUGGING, "WSAGetLastError: 0x%1x", dwStatus );
  482. return( true );
  483. }
  484. bool
  485. DecodeSocketStartupErrorCodes( DWORD dwStatus )
  486. {
  487. DWORD dwEventId;
  488. WCHAR szMsg[ 50 ]; //This string is just to hold a 32 bit number
  489. switch( dwStatus )
  490. {
  491. case WSASYSNOTREADY :
  492. dwEventId = MSG_WSANOTREADY;
  493. break;
  494. case WSAVERNOTSUPPORTED :
  495. dwEventId = MSG_WSAVERSION;
  496. break;
  497. case WSAEINVAL:
  498. dwEventId = MSG_WSAVERNOTSUPP;
  499. break;
  500. case WSAEPROCLIM:
  501. dwEventId = MSG_WSAEPROCLIM;
  502. break;
  503. case WSAEINPROGRESS:
  504. dwEventId = MSG_WSAEINPROGRESS;
  505. break;
  506. default:
  507. dwEventId = MSG_WSASTARTUPERRORCODE;
  508. break;
  509. }
  510. if( dwEventId == MSG_WSASTARTUPERRORCODE )
  511. {
  512. _snwprintf( szMsg,(sizeof(szMsg)/sizeof(WCHAR)) - 1, L"%lu", dwStatus );
  513. }
  514. else
  515. {
  516. lstrcpyW( szMsg, L" " );//no overflow. Source string is const wchar *
  517. }
  518. LogEvent( EVENTLOG_ERROR_TYPE, dwEventId, szMsg );
  519. _TRACE( TRACE_DEBUGGING, "WSAStartup error: 0x%1x", dwStatus );
  520. return( true );
  521. }
  522. bool
  523. FinishIncompleteIo( HANDLE hIoHandle, LPOVERLAPPED lpoObject, LPDWORD pdwNumBytes )
  524. {
  525. BOOL dwStatus;
  526. if( !( dwStatus = GetOverlappedResult( hIoHandle,
  527. lpoObject, pdwNumBytes, true ) ) )
  528. {
  529. DWORD dwErr = GetLastError();
  530. LogFormattedGetLastError( EVENTLOG_ERROR_TYPE, 0 , dwErr );
  531. _TRACE( TRACE_DEBUGGING, "Error: GetOverlappedResult() - 0x%1x",
  532. dwErr );
  533. return( false );
  534. }
  535. return( true );
  536. }
  537. bool
  538. GetProductType ( LPWSTR *pszProductType )
  539. {
  540. HKEY hkey;
  541. DWORD dwRetVal;
  542. bool ret = false;
  543. //
  544. // Query the registry for the product type.
  545. //
  546. dwRetVal = RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_PRODUCT_OPTION,
  547. 0, KEY_READ, &hkey);
  548. if(dwRetVal != ERROR_SUCCESS )
  549. {
  550. _TRACE( TRACE_DEBUGGING, "Error: RegOpenKeyEx() -- 0x%1x", dwRetVal);
  551. LogEvent( EVENTLOG_ERROR_TYPE, MSG_REGISTRYKEY, REG_PRODUCT_OPTION );
  552. goto Done;
  553. }
  554. if( !GetRegistryString( hkey, NULL, L"ProductType", pszProductType, L"",FALSE ) )
  555. {
  556. goto Done;
  557. }
  558. ret = true;
  559. Done:
  560. if(hkey)
  561. RegCloseKey (hkey);
  562. return ret;
  563. }
  564. void LogFormattedGetLastError( WORD dwType, DWORD dwMsg, DWORD dwErr )
  565. {
  566. LPTSTR lpString = NULL;
  567. GetErrMsgString( dwErr, &lpString );
  568. if (NULL != lpString)
  569. {
  570. LogEvent( dwType, dwMsg, lpString );
  571. LocalFree( lpString );
  572. }
  573. }
  574. bool
  575. GetWindowsVersion( bool *bNtVersionGTE5 )
  576. {
  577. _chASSERT( bNtVersionGTE5 );
  578. if( !bNtVersionGTE5 )
  579. {
  580. return( FALSE );
  581. }
  582. DWORD dwRetVal;
  583. HKEY hk;
  584. LPWSTR m_pszOsVersion;
  585. *bNtVersionGTE5 = false;
  586. if( ( dwRetVal = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_WINNT_VERSION, 0,
  587. KEY_QUERY_VALUE, &hk ) ) != ERROR_SUCCESS )
  588. {
  589. _TRACE( TRACE_DEBUGGING, "Error: RegOpenKeyEx() -- 0x%1x", dwRetVal);
  590. LogEvent( EVENTLOG_ERROR_TYPE, MSG_REGISTRYKEY, REG_WINNT_VERSION );
  591. return( FALSE );
  592. }
  593. else
  594. {
  595. if( !GetRegistryString( hk, NULL, L"CurrentVersion", &m_pszOsVersion, L"",FALSE ) )
  596. {
  597. return( FALSE );
  598. }
  599. if( wcscmp( m_pszOsVersion, L"5.0" ) >= 0 )
  600. {
  601. *bNtVersionGTE5 = true;
  602. }
  603. delete[] m_pszOsVersion;
  604. m_pszOsVersion = NULL;
  605. RegCloseKey( hk );
  606. }
  607. return( TRUE );
  608. }
  609. void InitializeOverlappedStruct( LPOVERLAPPED poObject )
  610. {
  611. _chASSERT( poObject != NULL );
  612. if( !poObject )
  613. {
  614. return;
  615. }
  616. poObject->Internal = 0;
  617. poObject->InternalHigh = 0;
  618. poObject->Offset = 0;
  619. poObject->OffsetHigh = 0;
  620. _chVERIFY2( poObject->hEvent = CreateEvent( NULL, TRUE, FALSE, NULL) );
  621. return;
  622. }
  623. bool
  624. CreateReadOrWritePipe ( LPHANDLE lphRead, LPHANDLE lphWrite,
  625. SECURITY_DESCRIPTOR* lpSecDesc, bool pipeMode )
  626. {
  627. _chASSERT( lphRead != NULL );
  628. _chASSERT( lphWrite != NULL );
  629. _chASSERT( ( pipeMode == READ_PIPE ) || ( pipeMode == WRITE_PIPE ) );
  630. if( !lphRead || !lphWrite ||
  631. ( ( pipeMode != READ_PIPE ) && ( pipeMode != WRITE_PIPE ) ) )
  632. {
  633. return FALSE;
  634. }
  635. TCHAR szPipeName[ MAX_PATH ];
  636. bool bUniqueName = false;
  637. SECURITY_ATTRIBUTES sa;
  638. sa.nLength = sizeof( sa );
  639. sa.lpSecurityDescriptor = lpSecDesc;
  640. switch( pipeMode )
  641. {
  642. case WRITE_PIPE: sa.bInheritHandle = TRUE;
  643. break;
  644. case READ_PIPE: sa.bInheritHandle = FALSE;
  645. break;
  646. }
  647. bUniqueName = GetUniquePipeName ( &szPipeName[0], &sa );
  648. if(!bUniqueName)
  649. {
  650. _TRACE(TRACE_DEBUGGING, "Error : Could not get a unique pipe name");
  651. return(FALSE);
  652. }
  653. *lphRead = CreateNamedPipe( szPipeName,
  654. PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED |
  655. #ifdef FILE_FLAG_FIRST_PIPE_INSTANCE
  656. FILE_FLAG_FIRST_PIPE_INSTANCE, // Good, the system supports it, use it for additional security
  657. #else
  658. 0,
  659. #endif
  660. PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1,
  661. NET_BUF_SIZ, NET_BUF_SIZ, 0, &sa );
  662. //_chASSERT( *lphRead != INVALID_HANDLE_VALUE );
  663. if( INVALID_HANDLE_VALUE == *lphRead )
  664. {
  665. return ( FALSE );
  666. }
  667. switch( pipeMode )
  668. {
  669. case WRITE_PIPE: sa.bInheritHandle = FALSE;
  670. break;
  671. case READ_PIPE: sa.bInheritHandle = TRUE;
  672. break;
  673. }
  674. *lphWrite = CreateFile( szPipeName, GENERIC_WRITE, 0, &sa, OPEN_EXISTING,
  675. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_WRITE_THROUGH
  676. |SECURITY_IDENTIFICATION |SECURITY_SQOS_PRESENT,
  677. NULL );
  678. _chASSERT( *lphWrite != INVALID_HANDLE_VALUE );
  679. if( INVALID_HANDLE_VALUE == *lphWrite )
  680. {
  681. TELNET_CLOSE_HANDLE( *lphRead );
  682. return ( FALSE );
  683. }
  684. return ( TRUE );
  685. }
  686. bool
  687. GetUniquePipeName ( LPTSTR pszPipeName, SECURITY_ATTRIBUTES *sa )
  688. {
  689. /*++
  690. Fix for MSRC issue 567 :
  691. Upon a telnet session instantiation, the telnet server process (tlntsvr.exe) creates
  692. two pipes for standard output and input of the command shell.
  693. These handles are then propagated to tlntsess.exe and cmd.exe.
  694. However, should the pipe be created prior to the telnet session instantiation,
  695. the telnet server process will connect to the application which has created the pipe
  696. rather than the telnet server process as would normally do.
  697. Fix :
  698. Basically, since the pipename that we were generating before, was easy to guess,
  699. it was possible to create a server side pipe instance even before it's actually created
  700. by the server process. So this function is added which will create a pipe name with
  701. random number appended to the PIPE_NAME_FORMAT_STRING ( earlier it was a
  702. number which was incremented everytime ). After the name creation, this function
  703. will also check whether pipe with that name already exists. If yes, it'll keep on
  704. generating new names till it finds a name for which the pipe does not exist. This
  705. name will be returned to the calling function.
  706. --*/
  707. static BOOL firstTime = TRUE;
  708. HANDLE hPipeHandle = INVALID_HANDLE_VALUE;
  709. ULONG ulRandomNumber = 0;
  710. int iCounter=0;
  711. if(g_hProv == NULL)
  712. {
  713. if (!CryptAcquireContext(&g_hProv,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT))
  714. {
  715. _TRACE(TRACE_DEBUGGING,L"Acquiring crypt context failed with error %d",GetLastError());
  716. return (FALSE);
  717. }
  718. }
  719. while ( iCounter++ < MAX_ATTEMPTS )
  720. {
  721. CryptGenRandom(g_hProv,sizeof(ulRandomNumber ),(PBYTE)&ulRandomNumber );
  722. _snwprintf( pszPipeName, MAX_PATH-1,PIPE_NAME_FORMAT_STRING, ulRandomNumber );
  723. hPipeHandle = CreateFile( pszPipeName, MAXIMUM_ALLOWED, 0,
  724. sa, OPEN_EXISTING,
  725. FILE_ATTRIBUTE_NORMAL
  726. | FILE_FLAG_OVERLAPPED
  727. | FILE_FLAG_WRITE_THROUGH
  728. | SECURITY_ANONYMOUS
  729. |SECURITY_SQOS_PRESENT,
  730. NULL
  731. );
  732. if(INVALID_HANDLE_VALUE == hPipeHandle && GetLastError() == ERROR_FILE_NOT_FOUND)
  733. break;
  734. TELNET_CLOSE_HANDLE(hPipeHandle);
  735. }
  736. return(INVALID_HANDLE_VALUE == hPipeHandle);
  737. }
  738. extern "C" void TlntCloseHandle(
  739. BOOL synchronize,
  740. HANDLE *handle_to_close
  741. )
  742. {
  743. if (synchronize)
  744. {
  745. TlntSynchronizeOn(g_hSyncCloseHandle);
  746. }
  747. if ((NULL != *handle_to_close) && (INVALID_HANDLE_VALUE != *handle_to_close))
  748. {
  749. CloseHandle (*handle_to_close);
  750. *handle_to_close = INVALID_HANDLE_VALUE;
  751. }
  752. if (synchronize)
  753. {
  754. ReleaseMutex(g_hSyncCloseHandle);
  755. }
  756. }
  757. extern "C" bool TlntSynchronizeOn(
  758. HANDLE object
  759. )
  760. {
  761. if ((INVALID_HANDLE_VALUE == object) || (NULL == object))
  762. {
  763. return false;
  764. }
  765. return (WAIT_OBJECT_0 == WaitForSingleObject(object, INFINITE )) ? true : false;
  766. }
  767. /*
  768. Description:
  769. Set SO_EXCLUSIVEADDRUSE on a socket.
  770. Parameters:
  771. [in] socket
  772. Return Values: On error, returns SOCKET_ERROR.
  773. */
  774. int SafeSetSocketOptions(SOCKET s)
  775. {
  776. int iStatus;
  777. int iSet = 1;
  778. iStatus = setsockopt( s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE , ( char* ) &iSet,
  779. sizeof( iSet ) );
  780. return ( iStatus );
  781. }
  782. // The following is copied from sids.c in common\func
  783. // To get rid of compilation issues all the names of the functions are changed.
  784. /*
  785. Name: TnFreeStandardSids
  786. Function: freeds the constant SIDS created by TnInitializeStandardSids
  787. Return: N/A (void)
  788. Notes: This function is a NOP, if it had been successfully called before and/or
  789. the TnInitializeStandardSids hasn't been called yet.
  790. constructor: call TnInitializeStandardSids when these sids are needed.
  791. */
  792. VOID TnFreeStandardSids(void)
  793. {
  794. if ( NULL != administratorsSid )
  795. {
  796. FreeSid(administratorsSid);
  797. administratorsSid = NULL;
  798. }
  799. if ( NULL != localSystemSid )
  800. {
  801. FreeSid(localSystemSid);
  802. localSystemSid = NULL;
  803. }
  804. if ( NULL != localLocalSid )
  805. {
  806. FreeSid(localLocalSid);
  807. localLocalSid = NULL;
  808. }
  809. if ( NULL != localNetworkSid )
  810. {
  811. FreeSid(localNetworkSid);
  812. localNetworkSid = NULL;
  813. }
  814. if ( NULL != everyoneSid )
  815. {
  816. FreeSid(everyoneSid);
  817. everyoneSid = NULL;
  818. }
  819. }
  820. /*
  821. Name: TnInitializeStandardSids
  822. Function: Builds the constant SIDS for use by various modules
  823. The sids built are
  824. Administrators, Everyone, LocalSystem
  825. Return: boolean to indicate success or not
  826. Notes: This function is a NOP, if it had been successfully called before and
  827. the built sids haven't been freed it.
  828. Destructor: call TnFreeStandardSids when these sids are no longer needed
  829. */
  830. BOOL TnInitializeStandardSids(void)
  831. {
  832. SID_IDENTIFIER_AUTHORITY localSystemAuthority = SECURITY_NT_AUTHORITY;
  833. SID_IDENTIFIER_AUTHORITY worldAuthority = SECURITY_WORLD_SID_AUTHORITY;
  834. if ( (NULL != administratorsSid) &&
  835. (NULL != everyoneSid) &&
  836. (NULL != localSystemSid) &&
  837. (NULL != localLocalSid) &&
  838. (NULL != localNetworkSid)
  839. )
  840. {
  841. return TRUE;
  842. }
  843. TnFreeStandardSids(); // In case only some of them were available
  844. //Build administrators alias sid
  845. if ( ! AllocateAndInitializeSid(
  846. &localSystemAuthority,
  847. 2, /* there are only two sub-authorities */
  848. SECURITY_BUILTIN_DOMAIN_RID,
  849. DOMAIN_ALIAS_RID_ADMINS,
  850. 0,0,0,0,0,0, /* Don't care about the rest */
  851. &administratorsSid
  852. ) )
  853. {
  854. goto CLEAN_UP;
  855. }
  856. //Build LocalSystem sid
  857. if ( ! AllocateAndInitializeSid(
  858. &localSystemAuthority,
  859. 1, /* there is only two sub-authority */
  860. SECURITY_LOCAL_SYSTEM_RID,
  861. 0,0,0,0,0,0,0, /* Don't care about the rest */
  862. &localSystemSid
  863. ) )
  864. {
  865. goto CLEAN_UP;
  866. }
  867. #ifndef SECURITY_LOCAL_SERVICE_RID
  868. #define SECURITY_LOCAL_SERVICE_RID (0x00000013L)
  869. #define SECURITY_NETWORK_SERVICE_RID (0x00000014L)
  870. #endif
  871. //Build LocalLocal sid
  872. if ( ! AllocateAndInitializeSid(
  873. &localSystemAuthority,
  874. 1, /* there is only two sub-authority */
  875. SECURITY_LOCAL_SERVICE_RID,
  876. 0,0,0,0,0,0,0, /* Don't care about the rest */
  877. &localLocalSid
  878. ) )
  879. {
  880. goto CLEAN_UP;
  881. }
  882. //Build LocalSystem sid
  883. if ( ! AllocateAndInitializeSid(
  884. &localSystemAuthority,
  885. 1, /* there is only two sub-authority */
  886. SECURITY_NETWORK_SERVICE_RID,
  887. 0,0,0,0,0,0,0, /* Don't care about the rest */
  888. &localNetworkSid
  889. ) )
  890. {
  891. goto CLEAN_UP;
  892. }
  893. //Build EveryOne alias sid
  894. if ( ! AllocateAndInitializeSid(
  895. &worldAuthority,
  896. 1, /* there is only two sub-authority*/
  897. SECURITY_WORLD_RID,
  898. 0,0,0,0,0,0,0, /* Don't care about the rest */
  899. &everyoneSid
  900. ) )
  901. {
  902. goto CLEAN_UP;
  903. }
  904. return TRUE;
  905. CLEAN_UP:
  906. TnFreeStandardSids();
  907. return FALSE;
  908. }
  909. PSID TnGetAdministratorsSid(void)
  910. {
  911. return administratorsSid;
  912. }
  913. PSID TnGetLocalSystemSid(void)
  914. {
  915. return localSystemSid;
  916. }
  917. PSID TnGetLocalLocalSid(void)
  918. {
  919. return localLocalSid;
  920. }
  921. PSID TnGetLocalNetworkSid(void)
  922. {
  923. return localNetworkSid;
  924. }
  925. PSID TnGetEveryoneSid(void)
  926. {
  927. return everyoneSid;
  928. }
  929. /*
  930. Name: TnCreateFile
  931. Function: Creates a file.
  932. This will result in the following acls :
  933. BUILTIN\Administrators:F
  934. NT AUTHORITY\SYSTEM:F
  935. Return: HANDLE
  936. */
  937. HANDLE TnCreateFile(LPCTSTR lpFileName,
  938. DWORD dwDesiredAccess,
  939. DWORD dwSharedMode,
  940. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  941. DWORD dwCreationDisposition,
  942. DWORD dwFlagsAndAttributes,
  943. HANDLE hTemplateFile
  944. )
  945. {
  946. BOOL fCreatedLocally = (lpSecurityAttributes) ? FALSE : TRUE;
  947. HANDLE handle = TnCreateFileEx(lpFileName,
  948. dwDesiredAccess,
  949. dwSharedMode,
  950. &lpSecurityAttributes,
  951. dwCreationDisposition,
  952. dwFlagsAndAttributes,
  953. hTemplateFile
  954. );
  955. if(fCreatedLocally)
  956. {
  957. TnFreeSecurityAttributes(&lpSecurityAttributes);
  958. }
  959. return(handle);
  960. }
  961. /*
  962. Name: TnCreateFileEx
  963. Function: Creates a file.
  964. This will result in the following acls :
  965. BUILTIN\Administrators:F
  966. NT AUTHORITY\SYSTEM:F
  967. Return: HANDLE
  968. */
  969. HANDLE TnCreateFileEx(LPCTSTR lpFileName,
  970. DWORD dwDesiredAccess,
  971. DWORD dwSharedMode,
  972. LPSECURITY_ATTRIBUTES *lplpSecurityAttributes,
  973. DWORD dwCreationDisposition,
  974. DWORD dwFlagsAndAttributes,
  975. HANDLE hTemplateFile
  976. )
  977. {
  978. //
  979. // no parameter checking - we pass on all parameters passed down to the createfile api
  980. //
  981. HANDLE handle = INVALID_HANDLE_VALUE;
  982. BOOL fCreatedLocally = FALSE;
  983. if (!lplpSecurityAttributes)
  984. {
  985. goto exit;
  986. }
  987. if(!(*lplpSecurityAttributes))
  988. {
  989. if (!TnCreateDefaultSecurityAttributes(lplpSecurityAttributes))
  990. goto exit;
  991. fCreatedLocally = TRUE;
  992. }
  993. handle = CreateFileW(lpFileName,
  994. dwDesiredAccess,
  995. dwSharedMode,
  996. *lplpSecurityAttributes,
  997. dwCreationDisposition,
  998. dwFlagsAndAttributes,
  999. hTemplateFile
  1000. );
  1001. if (INVALID_HANDLE_VALUE != handle)
  1002. {
  1003. if ((CREATE_ALWAYS == dwCreationDisposition) && (ERROR_ALREADY_EXISTS == GetLastError()))
  1004. {
  1005. // For CREATE_ALWAYS disposition, for existing files, CreateFile() does not set the
  1006. // security attributes. So we will do that ourselves specially.
  1007. if (!SetKernelObjectSecurity(handle,
  1008. DACL_SECURITY_INFORMATION,
  1009. (*lplpSecurityAttributes)->lpSecurityDescriptor))
  1010. {
  1011. // We could not set the security descriptor. Cannot trust this file
  1012. CloseHandle(handle);
  1013. handle = INVALID_HANDLE_VALUE;
  1014. }
  1015. }
  1016. }
  1017. if(INVALID_HANDLE_VALUE == handle)
  1018. {
  1019. if(fCreatedLocally)
  1020. {
  1021. TnFreeSecurityAttributes(lplpSecurityAttributes);
  1022. }
  1023. }
  1024. exit:
  1025. return(handle);
  1026. }
  1027. /*
  1028. Name: TnCreateDirectory
  1029. Function: Creates a directory.
  1030. This will result in the following acls :
  1031. BUILTIN\Administrators:F
  1032. NT AUTHORITY\SYSTEM:F
  1033. Return: BOOL
  1034. */
  1035. BOOL TnCreateDirectory(LPCTSTR lpPathName,
  1036. LPSECURITY_ATTRIBUTES lpSecurityAttributes
  1037. )
  1038. {
  1039. BOOL fCreatedLocally = (lpSecurityAttributes) ? FALSE : TRUE,
  1040. fRetVal = TnCreateDirectoryEx(lpPathName,
  1041. &lpSecurityAttributes
  1042. );
  1043. if(fCreatedLocally)
  1044. {
  1045. TnFreeSecurityAttributes(&lpSecurityAttributes);
  1046. }
  1047. return(fRetVal);
  1048. }
  1049. /*
  1050. Name: TnCreateDirectoryEx
  1051. Function: Creates a directory.
  1052. This will result in the following acls :
  1053. BUILTIN\Administrators:F
  1054. NT AUTHORITY\SYSTEM:F
  1055. Return: BOOL
  1056. */
  1057. BOOL TnCreateDirectoryEx(LPCTSTR lpPathName,
  1058. LPSECURITY_ATTRIBUTES *lplpSecurityAttributes
  1059. )
  1060. {
  1061. //
  1062. // no parameter checking - we pass on all parameters passed down to the createfile api
  1063. //
  1064. BOOL fCreatedLocally = FALSE, fRetVal = FALSE;
  1065. if (!lplpSecurityAttributes)
  1066. {
  1067. goto exit;
  1068. }
  1069. if(!(*lplpSecurityAttributes))
  1070. {
  1071. if (!TnCreateDefaultSecurityAttributes(lplpSecurityAttributes))
  1072. goto exit;
  1073. fCreatedLocally = TRUE;
  1074. }
  1075. fRetVal = CreateDirectoryW(lpPathName,
  1076. *lplpSecurityAttributes
  1077. );
  1078. if(FALSE == fRetVal)
  1079. {
  1080. if(fCreatedLocally)
  1081. {
  1082. TnFreeSecurityAttributes(lplpSecurityAttributes);
  1083. }
  1084. }
  1085. exit:
  1086. return(fRetVal);
  1087. }
  1088. /*
  1089. Name: TnCreateMutex
  1090. Function: Creates a mutex.
  1091. This will result in the following acls :
  1092. BUILTIN\Administrators:F
  1093. NT AUTHORITY\SYSTEM:F
  1094. Return: HANDLE
  1095. */
  1096. HANDLE TnCreateMutex(LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  1097. BOOL bInitialOwner,
  1098. LPCTSTR lpName
  1099. )
  1100. {
  1101. BOOL fCreatedLocally = (lpSecurityAttributes) ? FALSE : TRUE;
  1102. HANDLE handle = TnCreateMutexEx(&lpSecurityAttributes,
  1103. bInitialOwner,
  1104. lpName
  1105. );
  1106. if(fCreatedLocally)
  1107. {
  1108. TnFreeSecurityAttributes(&lpSecurityAttributes);
  1109. }
  1110. return(handle);
  1111. }
  1112. /*
  1113. Name: TnCreateMutexEx
  1114. Function: Creates a mutex.
  1115. This will result in the following acls :
  1116. BUILTIN\Administrators:F
  1117. NT AUTHORITY\SYSTEM:F
  1118. Return: HANDLE
  1119. */
  1120. HANDLE TnCreateMutexEx (LPSECURITY_ATTRIBUTES *lplpSecurityAttributes,
  1121. BOOL bInitialOwner,
  1122. LPCTSTR lpName
  1123. )
  1124. {
  1125. HANDLE handle = INVALID_HANDLE_VALUE;
  1126. BOOL fCreatedLocally = FALSE;
  1127. //
  1128. // no parameter checking - we pass on all parameters passed down to the createfile api
  1129. //
  1130. if (!lplpSecurityAttributes)
  1131. {
  1132. goto exit;
  1133. }
  1134. if(!(*lplpSecurityAttributes))
  1135. {
  1136. if (!TnCreateDefaultSecurityAttributes(lplpSecurityAttributes))
  1137. goto exit;
  1138. fCreatedLocally = TRUE;
  1139. }
  1140. handle = CreateMutexW(*lplpSecurityAttributes,
  1141. bInitialOwner,
  1142. lpName
  1143. );
  1144. if(INVALID_HANDLE_VALUE == handle)
  1145. {
  1146. if(fCreatedLocally)
  1147. {
  1148. TnFreeSecurityAttributes(lplpSecurityAttributes);
  1149. }
  1150. }
  1151. exit:
  1152. return(handle);
  1153. }
  1154. /*
  1155. Name: TnCreateDefaultSecurityAttributes
  1156. Function: Creates a default SECURITY_ATTRIBUTES.
  1157. Return: VOID
  1158. */
  1159. BOOL TnCreateDefaultSecurityAttributes(LPSECURITY_ATTRIBUTES *lplpSecurityAttributes )
  1160. {
  1161. PSECURITY_DESCRIPTOR pSecDesc = NULL;
  1162. BOOL fCreatedLocally = FALSE;
  1163. if (!lplpSecurityAttributes)
  1164. goto exit;
  1165. if(!(*lplpSecurityAttributes))
  1166. {
  1167. *lplpSecurityAttributes = (LPSECURITY_ATTRIBUTES) malloc( sizeof(SECURITY_ATTRIBUTES));
  1168. fCreatedLocally = TRUE;
  1169. }
  1170. if(!(*lplpSecurityAttributes))
  1171. goto exit;
  1172. if(!TnCreateDefaultSecDesc(&pSecDesc,0))
  1173. goto exit;
  1174. // Check on bInheritHandle
  1175. (*lplpSecurityAttributes)->nLength = sizeof(SECURITY_ATTRIBUTES);
  1176. (*lplpSecurityAttributes)->bInheritHandle = FALSE;
  1177. (*lplpSecurityAttributes)->lpSecurityDescriptor = pSecDesc;
  1178. return TRUE;
  1179. exit:
  1180. if(pSecDesc)
  1181. free(pSecDesc);
  1182. if(fCreatedLocally && lplpSecurityAttributes && (*lplpSecurityAttributes))
  1183. {
  1184. free(*lplpSecurityAttributes);
  1185. *lplpSecurityAttributes = NULL;
  1186. }
  1187. return FALSE;
  1188. }
  1189. /*
  1190. Name: TnFreeSecurityAttributes
  1191. */
  1192. VOID TnFreeSecurityAttributes(LPSECURITY_ATTRIBUTES *lplpSecurityAttributes)
  1193. {
  1194. if (lplpSecurityAttributes && (*lplpSecurityAttributes))
  1195. {
  1196. if((*lplpSecurityAttributes)->lpSecurityDescriptor)
  1197. {
  1198. free((*lplpSecurityAttributes)->lpSecurityDescriptor);
  1199. (*lplpSecurityAttributes)->lpSecurityDescriptor = NULL;
  1200. }
  1201. free(*lplpSecurityAttributes);
  1202. *lplpSecurityAttributes = NULL;
  1203. }
  1204. }
  1205. /*
  1206. Name: TnCreateDefaultSecDesc
  1207. Function: Creates a self-relative security descriptor
  1208. with full access to Administrator and LocalSystem.
  1209. Access to Everyone is as specified by the caller
  1210. Notes: The memory for the security descriptor is allocated
  1211. within this function and has to be freed with free()
  1212. Return: TRUE for success, else FALSE
  1213. */
  1214. BOOL TnCreateDefaultSecDesc( PSECURITY_DESCRIPTOR *ppSecDesc, DWORD EveryoneAccessMask )
  1215. {
  1216. BOOL retVal = FALSE;
  1217. PACL dacl = NULL;
  1218. DWORD aclSize = 0, lenSecDesc = 0;
  1219. SECURITY_DESCRIPTOR AbsSecDesc;
  1220. if(! TnInitializeStandardSids())
  1221. {
  1222. return retVal;
  1223. }
  1224. if(EveryoneAccessMask)
  1225. {
  1226. aclSize = sizeof(ACL) + (4* sizeof(ACCESS_ALLOWED_ACE)) + GetLengthSid(TnGetAdministratorsSid()) + GetLengthSid(TnGetLocalSystemSid()) + GetLengthSid(TnGetEveryoneSid()) + GetLengthSid(TnGetLocalLocalSid()) - (4*sizeof(DWORD));
  1227. }
  1228. else
  1229. {
  1230. aclSize = sizeof(ACL) + (3* sizeof(ACCESS_ALLOWED_ACE)) + GetLengthSid(TnGetAdministratorsSid()) + GetLengthSid(TnGetLocalSystemSid()) + GetLengthSid(TnGetLocalLocalSid()) - (3*sizeof(DWORD));
  1231. }
  1232. dacl = (PACL)malloc(aclSize);
  1233. if(!dacl)
  1234. {
  1235. goto Error;
  1236. }
  1237. SfuZeroMemory(dacl, sizeof(dacl));
  1238. if(!InitializeAcl(dacl, aclSize, ACL_REVISION))
  1239. {
  1240. goto Error;
  1241. }
  1242. if(!AddAccessAllowedAce(dacl, ACL_REVISION, GENERIC_ALL, TnGetAdministratorsSid()))
  1243. {
  1244. goto Error;
  1245. }
  1246. if(!AddAccessAllowedAce(dacl, ACL_REVISION, GENERIC_ALL, TnGetLocalSystemSid()))
  1247. {
  1248. goto Error;
  1249. }
  1250. if(!AddAccessAllowedAce(dacl, ACL_REVISION, GENERIC_ALL, TnGetLocalLocalSid()))
  1251. {
  1252. goto Error;
  1253. }
  1254. /*
  1255. if(!AddAccessAllowedAce(dacl, ACL_REVISION, GENERIC_ALL, TnGetLocalNetworkSid()))
  1256. {
  1257. goto Error;
  1258. }
  1259. */
  1260. if(EveryoneAccessMask)
  1261. {
  1262. if(!AddAccessAllowedAce(dacl, ACL_REVISION, EveryoneAccessMask, TnGetEveryoneSid()))
  1263. {
  1264. goto Error;
  1265. }
  1266. }
  1267. if(!InitializeSecurityDescriptor(&AbsSecDesc, SECURITY_DESCRIPTOR_REVISION))
  1268. {
  1269. goto Error;
  1270. }
  1271. if(! SetSecurityDescriptorDacl(&AbsSecDesc, TRUE, dacl, FALSE))
  1272. {
  1273. goto Error;
  1274. }
  1275. lenSecDesc = GetSecurityDescriptorLength(&AbsSecDesc);
  1276. *ppSecDesc = (PSECURITY_DESCRIPTOR)malloc(lenSecDesc);
  1277. if(!*ppSecDesc)
  1278. {
  1279. goto Error;
  1280. }
  1281. SfuZeroMemory(*ppSecDesc, lenSecDesc);
  1282. if (!MakeSelfRelativeSD(&AbsSecDesc, *ppSecDesc, &lenSecDesc))
  1283. {
  1284. if (*ppSecDesc)
  1285. {
  1286. free(*ppSecDesc);
  1287. *ppSecDesc = NULL;
  1288. }
  1289. goto Error;
  1290. }
  1291. retVal = TRUE;
  1292. Error:
  1293. TnFreeStandardSids();
  1294. if (dacl)
  1295. {
  1296. free(dacl);
  1297. }
  1298. return retVal;
  1299. }
  1300. // The following function is copy/pasted from common func library code
  1301. /**********************************************************************
  1302. * This function is functionally same as RegCreateKeyEx. But does something more &
  1303. * has one extra parameter e.g., the last parameter DWORD EveryoneAccessMask.
  1304. *
  1305. * If lpSecurityAttributes is NULL or lpSecurityAttributes->lpSecurityDescriptor is NULL,
  1306. * the fn creates or opens(if already exists) the reg key and apply a security descriptor
  1307. * on that key such that,
  1308. * System:F, Admin:F and Everyone : as provideded
  1309. *
  1310. * If lpSecurityAttributes is not NULL & lpSecurityAttributes->lpSecurityDescriptor is
  1311. * also not NULL then EveryoneAccessMask is simply ignored.
  1312. **********************************************************************/
  1313. LONG TnSecureRegCreateKeyEx(
  1314. HKEY hKey, // handle to open key
  1315. LPCTSTR lpSubKey, // subkey name
  1316. DWORD Reserved, // reserved
  1317. LPTSTR lpClass, // class string
  1318. DWORD dwOptions, // special options
  1319. REGSAM samDesired, // desired security access
  1320. LPSECURITY_ATTRIBUTES lpSecurityAttributes, // inheritance
  1321. PHKEY phkResult, // key handle
  1322. LPDWORD lpdwDisposition, // disposition value buffer
  1323. DWORD EveryoneAccessMask
  1324. )
  1325. {
  1326. SECURITY_ATTRIBUTES sa = {0};
  1327. LONG lRetVal;
  1328. DWORD dwDisposition;
  1329. // This variable keeps track whether SD is created locally. Coz if created locally we have to free
  1330. // the corresponding mem location later in this function.
  1331. BOOL fCreatedLocally = FALSE;
  1332. sa.nLength = sizeof(sa);
  1333. sa.bInheritHandle = lpSecurityAttributes?lpSecurityAttributes->bInheritHandle:FALSE;
  1334. sa.lpSecurityDescriptor = lpSecurityAttributes?lpSecurityAttributes->lpSecurityDescriptor:NULL ;
  1335. if(sa.lpSecurityDescriptor == NULL)
  1336. {
  1337. fCreatedLocally = TRUE;
  1338. if (!TnCreateDefaultSecDesc(&sa.lpSecurityDescriptor, EveryoneAccessMask))
  1339. return -1;
  1340. }
  1341. // We are opening the key handle with WRITE_DAC access, cos if the key already exists we
  1342. // may require to change the ACL
  1343. lRetVal = RegCreateKeyEx(
  1344. hKey, // handle to open key
  1345. lpSubKey, // subkey name
  1346. Reserved, // reserved
  1347. lpClass, // class string
  1348. dwOptions, // special options
  1349. samDesired |WRITE_DAC, // desired security access
  1350. &sa, // inheritance
  1351. phkResult, // key handle
  1352. &dwDisposition // disposition value buffer
  1353. );
  1354. if (ERROR_SUCCESS == lRetVal)
  1355. {
  1356. if (lpdwDisposition)
  1357. {
  1358. *lpdwDisposition = dwDisposition;
  1359. }
  1360. // If the key already exists set the ACL properly.
  1361. if (REG_OPENED_EXISTING_KEY == dwDisposition)
  1362. {
  1363. lRetVal = RegSetKeySecurity(*phkResult, DACL_SECURITY_INFORMATION, sa.lpSecurityDescriptor);
  1364. if (ERROR_SUCCESS != lRetVal)
  1365. {
  1366. RegCloseKey(*phkResult);
  1367. goto cleanup;
  1368. }
  1369. }
  1370. lRetVal = RegCloseKey(*phkResult);
  1371. if (ERROR_SUCCESS == lRetVal)
  1372. {
  1373. // Now open the the handle again with user provided samDesired.
  1374. lRetVal = RegOpenKeyEx(
  1375. hKey, // handle to open key
  1376. lpSubKey, // subkey name
  1377. dwOptions, // reserved
  1378. samDesired, // security access mask
  1379. phkResult // handle to open key
  1380. );
  1381. }
  1382. }
  1383. cleanup:
  1384. if (fCreatedLocally)
  1385. free(sa.lpSecurityDescriptor);
  1386. return lRetVal;
  1387. }