sid.c
Upload User: caisha3
Upload Date: 2013-09-21
Package Size: 208739k
Code Size: 15k
Category:

Windows Develop

Development Platform:

Visual C++

  1. //*************************************************************
  2. //
  3. //  SID management functions.
  4. //
  5. //  THESE FUNCTIONS ARE WINDOWS NT SPECIFIC!!!!!
  6. //
  7. //  Microsoft Confidential
  8. //  Copyright (c) Microsoft Corporation 1995
  9. //  All rights reserved
  10. //
  11. //*************************************************************
  12. #include "uenv.h"
  13. /***************************************************************************
  14. * GetSidString
  15. *
  16. * Allocates and returns a string representing the sid of the current user
  17. * The returned pointer should be freed using DeleteSidString().
  18. *
  19. * Returns a pointer to the string or NULL on failure.
  20. *
  21. * History:
  22. * 26-Aug-92 Davidc     Created
  23. *
  24. ***************************************************************************/
  25. LPTSTR GetSidString(HANDLE UserToken)
  26. {
  27.     NTSTATUS NtStatus;
  28.     PSID UserSid;
  29.     UNICODE_STRING UnicodeString;
  30.     LPTSTR lpEnd;
  31. #ifndef UNICODE
  32.     STRING String;
  33. #endif
  34.     //
  35.     // Get the user sid
  36.     //
  37.     UserSid = GetUserSid(UserToken);
  38.     if (UserSid == NULL) {
  39.         DebugMsg((DM_WARNING, TEXT("GetSidString: GetUserSid returned NULL")));
  40.         return NULL;
  41.     }
  42.     //
  43.     // Convert user SID to a string.
  44.     //
  45.     NtStatus = RtlConvertSidToUnicodeString(
  46.                             &UnicodeString,
  47.                             UserSid,
  48.                             (BOOLEAN)TRUE // Allocate
  49.                             );
  50.     //
  51.     // We're finished with the user sid
  52.     //
  53.     DeleteUserSid(UserSid);
  54.     //
  55.     // See if the conversion to a string worked
  56.     //
  57.     if (!NT_SUCCESS(NtStatus)) {
  58.         DebugMsg((DM_WARNING, TEXT("GetSidString: RtlConvertSidToUnicodeString failed, status = 0x%x"),
  59.                  NtStatus));
  60.         return NULL;
  61.     }
  62. #ifdef UNICODE
  63.     return(UnicodeString.Buffer);
  64. #else
  65.     //
  66.     // Convert the string to ansi
  67.     //
  68.     NtStatus = RtlUnicodeStringToAnsiString(&String, &UnicodeString, TRUE);
  69.     RtlFreeUnicodeString(&UnicodeString);
  70.     if (!NT_SUCCESS(NtStatus)) {
  71.         DebugMsg((DM_WARNING, TEXT("GetSidString: RtlUnicodeStringToAnsiString failed, status = 0x%x"),
  72.                  status));
  73.         return NULL;
  74.     }
  75.     return(String.Buffer);
  76. #endif
  77. }
  78. /***************************************************************************
  79. * DeleteSidString
  80. *
  81. * Frees up a sid string previously returned by GetSidString()
  82. *
  83. * Returns nothing.
  84. *
  85. * History:
  86. * 26-Aug-92 Davidc     Created
  87. *
  88. ***************************************************************************/
  89. VOID DeleteSidString(LPTSTR SidString)
  90. {
  91. #ifdef UNICODE
  92.     UNICODE_STRING String;
  93.     RtlInitUnicodeString(&String, SidString);
  94.     RtlFreeUnicodeString(&String);
  95. #else
  96.     ANSI_STRING String;
  97.     RtlInitAnsiString(&String, SidString);
  98.     RtlFreeAnsiString(&String);
  99. #endif
  100. }
  101. /***************************************************************************
  102. * GetUserSid
  103. *
  104. * Allocs space for the user sid, fills it in and returns a pointer. Caller
  105. * The sid should be freed by calling DeleteUserSid.
  106. *
  107. * Note the sid returned is the user's real sid, not the per-logon sid.
  108. *
  109. * Returns pointer to sid or NULL on failure.
  110. *
  111. * History:
  112. * 26-Aug-92 Davidc      Created.
  113. ***************************************************************************/
  114. PSID GetUserSid (HANDLE UserToken)
  115. {
  116.     PTOKEN_USER pUser, pTemp;
  117.     PSID pSid;
  118.     DWORD BytesRequired = 200;
  119.     NTSTATUS status;
  120.     //
  121.     // Allocate space for the user info
  122.     //
  123.     pUser = (PTOKEN_USER)LocalAlloc(LMEM_FIXED, BytesRequired);
  124.     if (pUser == NULL) {
  125.         DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to allocate %d bytes"),
  126.                   BytesRequired));
  127.         return NULL;
  128.     }
  129.     //
  130.     // Read in the UserInfo
  131.     //
  132.     status = NtQueryInformationToken(
  133.                  UserToken,                 // Handle
  134.                  TokenUser,                 // TokenInformationClass
  135.                  pUser,                     // TokenInformation
  136.                  BytesRequired,             // TokenInformationLength
  137.                  &BytesRequired             // ReturnLength
  138.                  );
  139.     if (status == STATUS_BUFFER_TOO_SMALL) {
  140.         //
  141.         // Allocate a bigger buffer and try again.
  142.         //
  143.         pTemp = LocalReAlloc(pUser, BytesRequired, LMEM_MOVEABLE);
  144.         if (pTemp == NULL) {
  145.             DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to allocate %d bytes"),
  146.                       BytesRequired));
  147.             LocalFree (pUser);
  148.             return NULL;
  149.         }
  150.         pUser = pTemp;
  151.         status = NtQueryInformationToken(
  152.                      UserToken,             // Handle
  153.                      TokenUser,             // TokenInformationClass
  154.                      pUser,                 // TokenInformation
  155.                      BytesRequired,         // TokenInformationLength
  156.                      &BytesRequired         // ReturnLength
  157.                      );
  158.     }
  159.     if (!NT_SUCCESS(status)) {
  160.         DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to query user info from user token, status = 0x%x"),
  161.                   status));
  162.         LocalFree(pUser);
  163.         return NULL;
  164.     }
  165.     BytesRequired = RtlLengthSid(pUser->User.Sid);
  166.     pSid = LocalAlloc(LMEM_FIXED, BytesRequired);
  167.     if (pSid == NULL) {
  168.         DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to allocate %d bytes"),
  169.                   BytesRequired));
  170.         LocalFree(pUser);
  171.         return NULL;
  172.     }
  173.     status = RtlCopySid(BytesRequired, pSid, pUser->User.Sid);
  174.     LocalFree(pUser);
  175.     if (!NT_SUCCESS(status)) {
  176.         DebugMsg((DM_WARNING, TEXT("GetUserSid: RtlCopySid Failed. status = %d"),
  177.                   status));
  178.         LocalFree(pSid);
  179.         pSid = NULL;
  180.     }
  181.     return pSid;
  182. }
  183. /***************************************************************************
  184. * DeleteUserSid
  185. *
  186. * Deletes a user sid previously returned by GetUserSid()
  187. *
  188. * Returns nothing.
  189. *
  190. * History:
  191. * 26-Aug-92 Davidc     Created
  192. *
  193. ***************************************************************************/
  194. VOID DeleteUserSid(PSID Sid)
  195. {
  196.     LocalFree(Sid);
  197. }
  198. //+--------------------------------------------------------------------------
  199. //
  200. //  Function:   AllocateAndInitSidFromString
  201. //
  202. //  Synopsis:   given the string representation of a SID, this function
  203. //              allocate and initializes a SID which the string represents
  204. //              For more information on the string representation of SIDs
  205. //              refer to ntseapi.h & ntrtl.h
  206. //
  207. //  Arguments:  [in] lpszSidStr : the string representation of the SID
  208. //              [out] pSID : the actual SID structure created from the string
  209. //
  210. //  Returns:    STATUS_SUCCESS : if the sid structure was successfully created
  211. //              or an error code based on errors that might occur
  212. //
  213. //  History:    10/6/1998  RahulTh  created
  214. //
  215. //---------------------------------------------------------------------------
  216. NTSTATUS AllocateAndInitSidFromString (const WCHAR* lpszSidStr, PSID* ppSid)
  217. {
  218.     WCHAR *     pSidStr = 0;
  219.     WCHAR*      pString = 0;
  220.     NTSTATUS    Status;
  221.     WCHAR*      pEnd = 0;
  222.     int         count;
  223.     BYTE        SubAuthCount;
  224.     DWORD       SubAuths[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  225.     ULONG       n;
  226.     SID_IDENTIFIER_AUTHORITY Auth;
  227.     pSidStr = LocalAlloc(LPTR, (lstrlen (lpszSidStr) + 1)*sizeof(WCHAR));;
  228.     if (!pSidStr)
  229.     {
  230.         Status = STATUS_NO_MEMORY;
  231.         goto AllocAndInitSidFromStr_End;
  232.     }
  233.     lstrcpy (pSidStr, lpszSidStr);
  234.     pString = pSidStr;
  235.     *ppSid = NULL;
  236.     count = 0;
  237.     do
  238.     {
  239.         pString = wcschr (pString, '-');
  240.         if (NULL == pString)
  241.             break;
  242.         count++;
  243.         pString++;
  244.     } while (1);
  245.     SubAuthCount = (BYTE)(count - 2);
  246.     if (0 > SubAuthCount || 8 < SubAuthCount)
  247.     {
  248.         Status = ERROR_INVALID_SID;
  249.         goto AllocAndInitSidFromStr_End;
  250.     }
  251.     pString = wcschr (pSidStr, L'-');
  252.     pString++;
  253.     pString = wcschr (pString, L'-'); //ignore the revision #
  254.     pString++;
  255.     pEnd = wcschr (pString, L'-');   //go to the beginning of subauths.
  256.     if (NULL != pEnd) *pEnd = L'';
  257.     Status = LoadSidAuthFromString (pString, &Auth);
  258.     if (STATUS_SUCCESS != Status)
  259.         goto AllocAndInitSidFromStr_End;
  260.     for (count = 0; count < SubAuthCount; count++)
  261.     {
  262.         pString = pEnd + 1;
  263.         pEnd = wcschr (pString, L'-');
  264.         if (pEnd)
  265.             *pEnd = L'';
  266.         Status = GetIntFromUnicodeString (pString, 10, &n);
  267.         if (STATUS_SUCCESS != Status)
  268.             goto AllocAndInitSidFromStr_End;
  269.         SubAuths[count] = n;
  270.     }
  271.     Status = RtlAllocateAndInitializeSid (&Auth, SubAuthCount,
  272.                                           SubAuths[0], SubAuths[1], SubAuths[2],
  273.                                           SubAuths[3], SubAuths[4], SubAuths[5],
  274.                                           SubAuths[6], SubAuths[7], ppSid);
  275. AllocAndInitSidFromStr_End:
  276.     if (pSidStr)
  277.         LocalFree( pSidStr );
  278.     return Status;
  279. }
  280. //+--------------------------------------------------------------------------
  281. //
  282. //  Function:   LoadSidAuthFromString
  283. //
  284. //  Synopsis:   given a string representing the SID authority (as it is
  285. //              normally represented in string format, fill the SID_AUTH..
  286. //              structure. For more details on the format of the string
  287. //              representation of the sid authority, refer to ntseapi.h and
  288. //              ntrtl.h
  289. //
  290. //  Arguments:  [in] pString : pointer to the unicode string
  291. //              [out] pSidAuth : pointer to the SID_IDENTIFIER_AUTH.. that is
  292. //                              desired
  293. //
  294. //  Returns:    STATUS_SUCCESS if it succeeds
  295. //              or an error code
  296. //
  297. //  History:    9/29/1998  RahulTh  created
  298. //
  299. //---------------------------------------------------------------------------
  300. NTSTATUS LoadSidAuthFromString (const WCHAR* pString,
  301.                                 PSID_IDENTIFIER_AUTHORITY pSidAuth)
  302. {
  303.     size_t len;
  304.     int i;
  305.     NTSTATUS Status;
  306.     const ULONG LowByteMask = 0xFF;
  307.     ULONG n;
  308.     len = lstrlenW (pString);
  309.     if (len > 2 && 'x' == pString[1])
  310.     {
  311.         //this is in hex.
  312.         //so we must have exactly 14 characters
  313.         //(2 each for each of the 6 bytes) + 2 for the leading 0x
  314.         if (14 != len)
  315.         {
  316.             Status = ERROR_INVALID_SID;
  317.             goto LoadAuthEnd;
  318.         }
  319.         for (i=0; i < 6; i++)
  320.         {
  321.             pString += 2;   //we need to skip the leading 0x
  322.             pSidAuth->Value[i] = (UCHAR)(((pString[0] - L'0') << 4) +
  323.                                          (pString[1] - L'0'));
  324.         }
  325.     }
  326.     else
  327.     {
  328.         //this is in decimal
  329.         Status = GetIntFromUnicodeString (pString, 10, &n);
  330.         if (Status != STATUS_SUCCESS)
  331.             goto LoadAuthEnd;
  332.         pSidAuth->Value[0] = pSidAuth->Value[1] = 0;
  333.         for (i = 5; i >=2; i--, n>>=8)
  334.             pSidAuth->Value[i] = (UCHAR)(n & LowByteMask);
  335.     }
  336.     Status = STATUS_SUCCESS;
  337. LoadAuthEnd:
  338.     return Status;
  339. }
  340. //+--------------------------------------------------------------------------
  341. //
  342. //  Function:   GetIntfromUnicodeString
  343. //
  344. //  Synopsis:   converts a unicode string into an integer
  345. //
  346. //  Arguments:  [in] szNum : the number represented as a unicode string
  347. //              [in] Base : the base in which the resultant int is desired
  348. //              [out] pValue : pointer to the integer representation of the
  349. //                             number
  350. //
  351. //  Returns:    STATUS_SUCCESS if successful.
  352. //              or some other error code
  353. //
  354. //  History:    9/29/1998  RahulTh  created
  355. //
  356. //---------------------------------------------------------------------------
  357. NTSTATUS GetIntFromUnicodeString (const WCHAR* szNum, ULONG Base, PULONG pValue)
  358. {
  359.     WCHAR * pwszNumStr = 0;
  360.     UNICODE_STRING StringW;
  361.     size_t len;
  362.     NTSTATUS Status;
  363.     len = lstrlen (szNum);
  364.     pwszNumStr = LocalAlloc( LPTR, (len + 1) * sizeof(WCHAR));
  365.     if (!pwszNumStr)
  366.     {
  367.         Status = STATUS_NO_MEMORY;
  368.         goto GetNumEnd;
  369.     }
  370.     lstrcpy (pwszNumStr, szNum);
  371.     StringW.Length = len * sizeof(WCHAR);
  372.     StringW.MaximumLength = StringW.Length + sizeof (WCHAR);
  373.     StringW.Buffer = pwszNumStr;
  374.     Status = RtlUnicodeStringToInteger (&StringW, Base, pValue);
  375. GetNumEnd:
  376.     if (pwszNumStr)
  377.         LocalFree( pwszNumStr );
  378.     return Status;
  379. }
  380. //*************************************************************
  381. //
  382. //  GetDomainSidFromRid()
  383. //
  384. //  Purpose:    Given one domain sid, constructs another domain sid
  385. //              by replacing the tail by the passed in Rid
  386. //
  387. //  Parameters: pSid            -   Given Domain Sid
  388. //              dwRid           -   Domain Rid
  389. //              ppNewSid        -   Pointer to the New Sid
  390. //
  391. //  Return:     ERROR_SUCCESS on Success
  392. //              FALSE if an error occurs
  393. //
  394. //  Comments:
  395. //      Sid returned must be freed using FreeSid.
  396. //
  397. //  History:    Date        Author     Comment
  398. //              6/6/95      ericflo    Created
  399. //
  400. //*************************************************************
  401. NTSTATUS GetDomainSidFromDomainRid(PSID pSid, DWORD dwRid, PSID *ppNewSid)
  402. {
  403.     
  404.     PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority;
  405.     // pointer to identifier authority
  406.     BYTE      nSubAuthorityCount, i;                   // count of subauthorities
  407.     DWORD     dwSubAuthority[8]={0,0,0,0,0,0,0,0};     // subauthority 
  408.     PUCHAR    pSubAuthCount;
  409.     DWORD    *pdwSubAuth;
  410.     NTSTATUS  Status=ERROR_SUCCESS;
  411.     
  412.     DmAssert(IsValidSid(pSid));
  413.     
  414.     //
  415.     // Will fail only if passed in sid is invalid and in the case 
  416.     // the returned value is undefined. 
  417.     //
  418.     
  419.     pIdentifierAuthority = RtlIdentifierAuthoritySid(pSid);
  420.     
  421.     //
  422.     // get the count of subauthorities
  423.     //
  424.     pSubAuthCount = RtlSubAuthorityCountSid (pSid);
  425.     
  426.     if (!pSubAuthCount) {
  427.         Status = ERROR_INVALID_SID;
  428.         goto Exit;
  429.     }
  430.     
  431.     nSubAuthorityCount = *pSubAuthCount;
  432.     
  433.     //
  434.     // get each of the subauthorities
  435.     //
  436.     for (i = 0; i < (nSubAuthorityCount-1); i++) {
  437.         pdwSubAuth = RtlSubAuthoritySid(pSid, i);
  438.         
  439.         if (!pdwSubAuth) {
  440.             Status = ERROR_INVALID_SID;
  441.             goto Exit;
  442.         }
  443.         
  444.         dwSubAuthority[i] = *pdwSubAuth;
  445.     }
  446.     
  447.     dwSubAuthority[i] = dwRid;
  448.     //
  449.     // Allocate a sid with these..
  450.     //
  451.     Status = RtlAllocateAndInitializeSid(
  452.                 pIdentifierAuthority,
  453.                 nSubAuthorityCount,
  454.                 dwSubAuthority[0],
  455.                 dwSubAuthority[1],
  456.                 dwSubAuthority[2],
  457.                 dwSubAuthority[3],
  458.                 dwSubAuthority[4],
  459.                 dwSubAuthority[5],
  460.                 dwSubAuthority[6],
  461.                 dwSubAuthority[7],
  462.                 ppNewSid
  463.                 );
  464.     
  465. Exit:
  466.     // Sid, All Done
  467.     return Status;
  468. }