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.

691 lines
19 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. wssid.cpp
  5. Abstract:
  6. This file gets the security identifier (SID) for respective user name and
  7. groups in the current access token on a local system or a remote system.
  8. Authors:
  9. Christophe Robert
  10. Revision History:
  11. 02-July-2001 : Updated by Wipro Technologies.
  12. --*/
  13. //common header files needed for this file
  14. #include "pch.h"
  15. #include "CommonHeaderFiles.h"
  16. WsSid::WsSid ( VOID )
  17. /*++
  18. Routine Description:
  19. This function intializes the members of WsSid class.
  20. Arguments:
  21. None
  22. Return Value:
  23. None
  24. --*/
  25. {
  26. // initializing member variables
  27. pSid = NULL ;
  28. bToBeFreed = FALSE ;
  29. }
  30. WsSid::~WsSid ( VOID )
  31. /*++
  32. Routine Description:
  33. This function deallocates the members of WsSid class.
  34. Arguments:
  35. None
  36. Return Value:
  37. None
  38. --*/
  39. {
  40. // release memory
  41. if ( bToBeFreed && pSid ){
  42. FreeMemory ( (LPVOID *) &pSid ) ;
  43. }
  44. }
  45. DWORD
  46. WsSid::DisplayAccountName (
  47. IN DWORD dwFormatType ,
  48. IN DWORD dwNameFormat
  49. )
  50. /*++
  51. Routine Description:
  52. This function displays the user name and SID.
  53. Arguments:
  54. [IN] DWORD dwFormatType : Format type i.,e LIST, CSV or TABLE
  55. [IN] DWORD dwNameFormat : Name Format either UPN or FQDN
  56. Return Value:
  57. EXIT_SUCCESS : On success
  58. EXIT_FAILURE : On failure
  59. --*/
  60. {
  61. // sub-local variables
  62. WCHAR wszUserName[ MAX_STRING_LENGTH ];
  63. WCHAR wszSid [ MAX_STRING_LENGTH ];
  64. WCHAR wszGroup[MAX_STRING_LENGTH];
  65. DWORD dwErr = 0 ;
  66. DWORD dwColCount = 0 ;
  67. DWORD dw = 0 ;
  68. DWORD dwCount = 0 ;
  69. DWORD dwArrSize = 0 ;
  70. DWORD dwSize = 0;
  71. DWORD dwUserLen = 0;
  72. DWORD dwSidLen = 0;
  73. DWORD dwUserColLen = 0;
  74. DWORD dwSidColLen = 0;
  75. DWORD dwSidUse = 0;
  76. LPWSTR wszBuffer = NULL;
  77. //initialize memory
  78. SecureZeroMemory ( wszUserName, SIZE_OF_ARRAY(wszUserName) );
  79. SecureZeroMemory ( wszSid, SIZE_OF_ARRAY(wszSid) );
  80. SecureZeroMemory ( wszGroup, SIZE_OF_ARRAY(wszGroup) );
  81. // create a dynamic array
  82. TARRAY pColData = CreateDynamicArray();
  83. if ( NULL == pColData)
  84. {
  85. // set last error and display an error message with respect
  86. //to ERROR_NOT_ENOUGH_MEMORY
  87. SetLastError((DWORD)E_OUTOFMEMORY);
  88. SaveLastError();
  89. ShowLastErrorEx (stderr, SLE_TYPE_ERROR | SLE_SYSTEM);
  90. return EXIT_FAILURE;
  91. }
  92. dwSize = SIZE_OF_ARRAY(wszGroup);
  93. //if /FQDN is specified
  94. if ( (FQDN_FORMAT == dwNameFormat) )
  95. {
  96. //Get the username in FQDN format
  97. if (GetUserNameEx ( NameFullyQualifiedDN, wszGroup, &dwSize) == FALSE )
  98. {
  99. // GetUserNameEx() got failed due to small size specified for username.
  100. // allocate the actual size (dwSize) of username and call the same
  101. // function again...
  102. wszBuffer = (LPWSTR) AllocateMemory(dwSize * sizeof(WCHAR));
  103. if ( NULL == wszBuffer )
  104. {
  105. // display system error message with respect to GetLastError()
  106. ShowLastErrorEx ( stderr, SLE_TYPE_ERROR | SLE_SYSTEM );
  107. return EXIT_FAILURE;
  108. }
  109. if (GetUserNameEx ( NameFullyQualifiedDN, wszBuffer, &dwSize) == FALSE )
  110. {
  111. // display an error messaga as.. unable to get FQDN name
  112. // as logged-on user is not a domain user
  113. ShowMessage ( stderr, GetResString (IDS_ERROR_FQDN) );
  114. DestroyDynamicArray(&pColData);
  115. FreeMemory ((LPVOID*) &wszBuffer);
  116. return EXIT_FAILURE ;
  117. }
  118. ShowMessage ( stdout, _X(wszBuffer));
  119. ShowMessage ( stdout, L"\n");
  120. FreeMemory ((LPVOID*) &wszBuffer);
  121. DestroyDynamicArray(&pColData);
  122. // return success
  123. return EXIT_SUCCESS;
  124. }
  125. ShowMessage ( stdout, _X(wszGroup));
  126. ShowMessage ( stdout, L"\n");
  127. DestroyDynamicArray(&pColData);
  128. // return success
  129. return EXIT_SUCCESS;
  130. }
  131. else if ( (UPN_FORMAT == dwNameFormat ) )
  132. {
  133. // get the user name in UPN format
  134. if ( GetUserNameEx ( NameUserPrincipal, wszGroup, &dwSize) == FALSE )
  135. {
  136. // GetUserNameEx() got failed due to small size specified for username
  137. // allocate the actual size(dwSize) of username and call the same
  138. // function again...
  139. wszBuffer = (LPWSTR) AllocateMemory(dwSize * sizeof(WCHAR));
  140. if ( NULL == wszBuffer )
  141. {
  142. // display system error message with respect to GetLastError()
  143. ShowLastErrorEx ( stderr, SLE_TYPE_ERROR | SLE_SYSTEM );
  144. return EXIT_FAILURE;
  145. }
  146. // get the user name in UPN format
  147. if ( GetUserNameEx ( NameUserPrincipal, wszBuffer, &dwSize) == FALSE )
  148. {
  149. // display an error messaga as.. unable to get UPN name
  150. // as logged-on user is not a domain user
  151. ShowMessage ( stderr, GetResString (IDS_ERROR_UPN) );
  152. // release memory
  153. DestroyDynamicArray(&pColData);
  154. FreeMemory ((LPVOID*) &wszBuffer);
  155. return EXIT_FAILURE ;
  156. }
  157. // convert UPN name in lower case letters
  158. CharLower ( wszBuffer );
  159. // display UPN name
  160. ShowMessage ( stdout, _X(wszBuffer) );
  161. ShowMessage ( stdout, L"\n");
  162. // release memory
  163. DestroyDynamicArray(&pColData);
  164. FreeMemory ((LPVOID*) &wszBuffer);
  165. //return success
  166. return EXIT_SUCCESS;
  167. }
  168. // convert UPN name in lower case letters
  169. CharLower ( wszGroup );
  170. // display UPN name
  171. ShowMessage ( stdout, _X(wszGroup) );
  172. ShowMessage ( stdout, L"\n");
  173. DestroyDynamicArray(&pColData);
  174. //return success
  175. return EXIT_SUCCESS;
  176. }
  177. // get user name
  178. if ( (dwErr = GetAccountName ( wszUserName, &dwSidUse)) != EXIT_SUCCESS ){
  179. // display an error message with respect to Win32 error code
  180. ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_SYSTEM);
  181. DestroyDynamicArray(&pColData);
  182. return dwErr ;
  183. }
  184. // convery user name in lower case letters
  185. CharLower ( wszUserName );
  186. // if /USER specified
  187. if ( USER_ONLY != dwNameFormat)
  188. {
  189. // display SID with respect to username
  190. if ( (dwErr = DisplaySid ( wszSid ) ) != EXIT_SUCCESS ){
  191. DestroyDynamicArray(&pColData);
  192. return dwErr ;
  193. }
  194. }
  195. // get the length of user name
  196. dwUserLen = StringLengthInBytes (wszUserName);
  197. // get the length of SID
  198. dwSidLen = StringLengthInBytes (wszSid);
  199. //
  200. //To avoid localization problems, get the maximum length of column name and
  201. // values of respective columns
  202. //
  203. // Get the maximum length of a column name "UserName"
  204. dwUserColLen = StringLengthInBytes( GetResString(IDS_COL_USERNAME) );
  205. if ( dwUserColLen > dwUserLen )
  206. {
  207. dwUserLen = dwUserColLen;
  208. }
  209. // Get the maximum length of a column name "SID"
  210. dwSidColLen = StringLengthInBytes( GetResString(IDS_COL_SID) );
  211. if ( dwSidColLen > dwSidLen )
  212. {
  213. dwSidLen = dwSidColLen;
  214. }
  215. // defining verbose columns with the actual size
  216. TCOLUMNS pVerboseCols[] =
  217. {
  218. {L"\0",dwUserLen, SR_TYPE_STRING, COL_FORMAT_STRING, NULL, NULL},
  219. {L"\0",dwSidLen,SR_TYPE_STRING,COL_FORMAT_STRING,NULL,NULL}
  220. };
  221. // if /USER is specified
  222. if ( USER_ONLY == dwNameFormat )
  223. {
  224. // display the user name
  225. StringCopy (pVerboseCols[dw].szColumn , GetResString(IDS_COL_USERNAME), MAX_RES_STRING);
  226. ShowMessage ( stdout, _X(wszUserName) );
  227. ShowMessage ( stdout, L"\n");
  228. // release memory
  229. DestroyDynamicArray(&pColData);
  230. return EXIT_SUCCESS;
  231. }
  232. else
  233. {
  234. //Load the column names for verbose mode
  235. for( dwColCount = IDS_COL_USERNAME , dw = 0 ; dwColCount <= IDS_COL_SID;
  236. dwColCount++, dw++)
  237. {
  238. StringCopy(pVerboseCols[dw].szColumn , GetResString(dwColCount), MAX_RES_STRING );
  239. }
  240. // get the number of columns
  241. dwArrSize = SIZE_OF_ARRAY( pVerboseCols );
  242. }
  243. //Start appending to the 2D array
  244. DynArrayAppendRow(pColData, dwArrSize);
  245. //Insert the user name
  246. DynArraySetString2(pColData, dwCount, USERNAME_COL_NUMBER, _X(wszUserName), 0);
  247. //Insert the SID string
  248. DynArraySetString2(pColData, dwCount, SID_COL_NUMBER, _X(wszSid), 0);
  249. // 1) If the display format is CSV.. then we should not display column headings..
  250. // 2) If /NH is specified ...then we should not display column headings..
  251. if ( !(( SR_FORMAT_CSV == dwFormatType ) || ((dwFormatType & SR_HIDECOLUMN) == SR_HIDECOLUMN)))
  252. {
  253. // display the headings before displaying the username and SID
  254. ShowMessage ( stdout, L"\n" );
  255. ShowMessage ( stdout, GetResString ( IDS_LIST_USER_NAMES ) );
  256. ShowMessage ( stdout, GetResString ( IDS_DISPLAY_USER_DASH ) );
  257. }
  258. // display the actual values for user name and SID
  259. ShowResults(dwArrSize, pVerboseCols, dwFormatType, pColData);
  260. // release memory
  261. DestroyDynamicArray(&pColData);
  262. // return success
  263. return EXIT_SUCCESS;
  264. }
  265. DWORD
  266. WsSid::DisplayGroupName ( OUT LPWSTR wszGroupName,
  267. OUT LPWSTR wszGroupSid,
  268. IN DWORD *dwSidUseName)
  269. /*++
  270. Routine Description:
  271. This function gets the group name and SID to display.
  272. Arguments:
  273. [OUT] LPWSTR wszGroupName : Stores group name
  274. [OUT] LPWSTR wszGroupSid : Stores group SID
  275. [IN] DWORD dwSidUseName : stores Sid use name
  276. Return Value:
  277. EXIT_SUCCESS : On success
  278. EXIT_FAILURE : On failure
  279. --*/
  280. {
  281. // sub-local variables
  282. DWORD dwErr = 0 ;
  283. DWORD dwSidUse = 0;
  284. // display the user name
  285. if ( (dwErr = GetAccountName ( wszGroupName, &dwSidUse) ) != EXIT_SUCCESS ){
  286. // display an error message with respect to Win32 error code
  287. ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_SYSTEM);
  288. return dwErr ;
  289. }
  290. // display SID
  291. if ( (dwErr = DisplaySid ( wszGroupSid ) ) != EXIT_SUCCESS ){
  292. return dwErr ;
  293. }
  294. *dwSidUseName = dwSidUse;
  295. // return success
  296. return EXIT_SUCCESS;
  297. }
  298. DWORD
  299. WsSid::DisplaySid (
  300. OUT LPWSTR wszSid
  301. )
  302. /*++
  303. Routine Description:
  304. This function gets the SID .
  305. Arguments:
  306. [OUT] LPWSTR wszSid : Stores SID string
  307. Return Value:
  308. EXIT_SUCCESS : On success
  309. EXIT_FAILURE : On failure
  310. --*/
  311. {
  312. // sub-local variable
  313. DWORD dwErr = 0 ;
  314. // Get SID string
  315. if ( (dwErr = GetSidString (wszSid)) != EXIT_SUCCESS )
  316. {
  317. return dwErr ;
  318. }
  319. // return success
  320. return EXIT_SUCCESS;
  321. }
  322. DWORD
  323. WsSid::GetAccountName (
  324. OUT LPWSTR wszAccountName,
  325. OUT DWORD *dwSidType
  326. )
  327. /*++
  328. Routine Description:
  329. This function gets the account name and SID
  330. Arguments:
  331. [OUT] szAccountName : Stores user name
  332. [OUT] dwSidType : Stores Sid use name
  333. Return Value:
  334. EXIT_SUCCESS : On success
  335. EXIT_FAILURE : On failure
  336. --*/
  337. {
  338. // sub-local variables
  339. SID_NAME_USE SidUse ;
  340. WCHAR wszUserName[ MAX_RES_STRING ];
  341. WCHAR wszDomainName [ MAX_RES_STRING ];
  342. DWORD dwUserLen = 0;
  343. DWORD dwDomainLen = 0;
  344. BOOL bNotResolved = FALSE;
  345. // initialize the variables
  346. SecureZeroMemory ( wszUserName, SIZE_OF_ARRAY(wszUserName) );
  347. SecureZeroMemory ( wszDomainName, SIZE_OF_ARRAY(wszDomainName) );
  348. // get the length of user name and group name
  349. dwUserLen = SIZE_OF_ARRAY ( wszUserName );
  350. dwDomainLen = SIZE_OF_ARRAY ( wszDomainName );
  351. // enable debug privileges
  352. if ( FALSE == EnableDebugPriv() )
  353. {
  354. // return WIN32 error code
  355. return GetLastError () ;
  356. }
  357. // get user name and domain name with respective to SID
  358. if ( FALSE == LookupAccountSid ( NULL, // Local System
  359. pSid,
  360. wszUserName,
  361. &dwUserLen,
  362. wszDomainName,
  363. &dwDomainLen,
  364. &SidUse ) ){
  365. if ( 0 == StringLength (wszUserName, 0))
  366. {
  367. bNotResolved = TRUE;
  368. StringCopy ( wszAccountName, L" ", MAX_RES_STRING );
  369. }
  370. else if ( ( 0 != StringLength (wszDomainName, 0) ) && ( 0 != StringLength (wszUserName, 0) ) ) {
  371. // return WIN32 error code
  372. return GetLastError () ;
  373. }
  374. }
  375. if ( FALSE == bNotResolved)
  376. {
  377. // check for empty domain name
  378. if ( 0 != StringLength ( wszDomainName, 0 ) ) {
  379. StringCopy ( wszAccountName, wszDomainName, MAX_RES_STRING );
  380. StringConcat ( wszAccountName, SLASH , MAX_RES_STRING);
  381. StringConcat ( wszAccountName, wszUserName, MAX_RES_STRING );
  382. }
  383. else {
  384. StringCopy ( wszAccountName, wszUserName, MAX_RES_STRING );
  385. }
  386. }
  387. *dwSidType = (DWORD)SidUse;
  388. // return success
  389. return EXIT_SUCCESS ;
  390. }
  391. DWORD
  392. WsSid::GetSidString (
  393. OUT LPWSTR wszSid
  394. )
  395. /*++
  396. Routine Description:
  397. This function gets the SID string.
  398. Arguments:
  399. [OUT] LPWSTR wszSid : Stores SID string
  400. Return Value:
  401. EXIT_SUCCESS : On success
  402. EXIT_FAILURE : On failure
  403. --*/
  404. {
  405. // sub-local variables
  406. PSID_IDENTIFIER_AUTHORITY Auth ;
  407. PUCHAR lpNbSubAuth ;
  408. LPDWORD lpSubAuth = 0 ;
  409. UCHAR uloop ;
  410. WCHAR wszTmp[MAX_RES_STRING] ;
  411. WCHAR wszStr[ MAX_RES_STRING ] ;
  412. // initialize the variables
  413. SecureZeroMemory ( wszTmp, SIZE_OF_ARRAY(wszTmp) );
  414. SecureZeroMemory ( wszStr, SIZE_OF_ARRAY(wszStr) );
  415. //check for empty
  416. if ( NULL == pSid )
  417. {
  418. return EXIT_FAILURE ;
  419. }
  420. //Is it a valid SID
  421. if ( FALSE == IsValidSid ( pSid ) ) {
  422. ShowMessage ( stderr, GetResString ( IDS_INVALID_SID ) );
  423. return EXIT_FAILURE ;
  424. }
  425. //Add the revision
  426. StringCopy ( wszStr, SID_STRING, MAX_RES_STRING );
  427. //Get identifier authority
  428. Auth = GetSidIdentifierAuthority ( pSid ) ;
  429. if ( NULL == Auth )
  430. {
  431. // return WIN32 error code
  432. return GetLastError () ;
  433. }
  434. // format authority value
  435. if ( (Auth->Value[0] != 0) || (Auth->Value[1] != 0) ) {
  436. StringCchPrintf ( wszTmp, SIZE_OF_ARRAY(wszTmp), AUTH_FORMAT_STR1 ,
  437. (ULONG)Auth->Value[0],
  438. (ULONG)Auth->Value[1],
  439. (ULONG)Auth->Value[2],
  440. (ULONG)Auth->Value[3],
  441. (ULONG)Auth->Value[4],
  442. (ULONG)Auth->Value[5] );
  443. }
  444. else {
  445. StringCchPrintf ( wszTmp, SIZE_OF_ARRAY(wszTmp), AUTH_FORMAT_STR2 ,
  446. (ULONG)(Auth->Value[5] ) +
  447. (ULONG)(Auth->Value[4] << 8) +
  448. (ULONG)(Auth->Value[3] << 16) +
  449. (ULONG)(Auth->Value[2] << 24) );
  450. }
  451. StringConcat (wszStr, DASH , SIZE_OF_ARRAY(wszStr));
  452. StringConcat (wszStr, wszTmp, SIZE_OF_ARRAY(wszStr));
  453. //Get sub authorities
  454. lpNbSubAuth = GetSidSubAuthorityCount ( pSid ) ;
  455. if ( NULL == lpNbSubAuth )
  456. {
  457. return GetLastError () ;
  458. }
  459. // loop through and get sub authority
  460. for ( uloop = 0 ; uloop < *lpNbSubAuth ; uloop++ ) {
  461. lpSubAuth = GetSidSubAuthority ( pSid,(DWORD)uloop ) ;
  462. if ( NULL == lpSubAuth )
  463. {
  464. return GetLastError () ;
  465. }
  466. // convert long integer to a string
  467. _ultot (*lpSubAuth, wszTmp, BASE_TEN) ;
  468. StringConcat ( wszStr, DASH, SIZE_OF_ARRAY(wszStr) ) ;
  469. StringConcat (wszStr, wszTmp, SIZE_OF_ARRAY(wszStr) ) ;
  470. }
  471. StringCopy ( wszSid, wszStr, MAX_RES_STRING );
  472. // retunr success
  473. return EXIT_SUCCESS ;
  474. }
  475. DWORD
  476. WsSid::Init (
  477. OUT PSID pOtherSid
  478. )
  479. /*++
  480. Routine Description:
  481. This function Initializes the SID
  482. Arguments:
  483. [OUT] PSID pOtherSid : Stores SID string
  484. Return Value:
  485. EXIT_SUCCESS : On success
  486. EXIT_FAILURE : On failure
  487. --*/
  488. {
  489. // sub-local variable
  490. DWORD dwSize ;
  491. // get the length of SID
  492. dwSize = GetLengthSid ( pOtherSid ) ;
  493. // allocate the memory with the actual size
  494. pSid = (PSID) AllocateMemory ( dwSize ) ;
  495. if ( NULL == pSid )
  496. {
  497. // return WIN32 error code
  498. return GetLastError () ;
  499. }
  500. bToBeFreed = TRUE ;
  501. // copy SID
  502. if ( FALSE == CopySid ( dwSize, pSid, pOtherSid ) ){
  503. return GetLastError () ;
  504. }
  505. // return success
  506. return EXIT_SUCCESS ;
  507. }
  508. BOOL
  509. WsSid::EnableDebugPriv()
  510. /*++
  511. Routine Description:
  512. Enables the debug privliges for the current process so that
  513. this utility can terminate the processes on local system without any problem
  514. Arguments:
  515. NONE
  516. Return Value:
  517. TRUE upon successfull and FALSE if failed
  518. --*/
  519. {
  520. // local variables
  521. LUID luidValue;
  522. BOOL bResult = FALSE;
  523. HANDLE hToken = NULL;
  524. TOKEN_PRIVILEGES tkp;
  525. // Retrieve a handle of the access token
  526. bResult = OpenProcessToken( GetCurrentProcess(),
  527. TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_QUERY, &hToken );
  528. if ( bResult == FALSE )
  529. {
  530. // save the error messaage and return
  531. SaveLastError();
  532. return FALSE;
  533. }
  534. // Enable the SE_DEBUG_NAME privilege or disable
  535. // all privileges, depends on this flag.
  536. bResult = LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &luidValue );
  537. if ( bResult == FALSE )
  538. {
  539. // save the error messaage and return
  540. SaveLastError();
  541. CloseHandle( hToken );
  542. return FALSE;
  543. }
  544. // prepare the token privileges structure
  545. tkp.PrivilegeCount = 1;
  546. tkp.Privileges[ 0 ].Luid = luidValue;
  547. tkp.Privileges[ 0 ].Attributes = SE_PRIVILEGE_ENABLED;
  548. // now enable the debug privileges in the token
  549. bResult = AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof( TOKEN_PRIVILEGES ),
  550. ( PTOKEN_PRIVILEGES ) NULL, ( PDWORD ) NULL );
  551. if ( bResult == FALSE )
  552. {
  553. // The return value of AdjustTokenPrivileges be texted
  554. SaveLastError();
  555. CloseHandle( hToken );
  556. return FALSE;
  557. }
  558. // close the opened handle object
  559. CloseHandle( hToken );
  560. // enabled ... inform success
  561. return TRUE;
  562. }