LSASAMP.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:13k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*++
  2. Managing user privileges can be achieved programmatically using the
  3. following steps:
  4. 1. Open the policy on the target machine with LsaOpenPolicy(). To grant
  5.    privileges, open the policy with POLICY_CREATE_ACCOUNT and
  6.    POLICY_LOOKUP_NAMES access. To revoke privileges, open the policy with
  7.    POLICY_LOOKUP_NAMES access.
  8. 2. Obtain a SID (security identifier) representing the user/group of
  9.    interest. The LookupAccountName() and LsaLookupNames() APIs can obtain a
  10.    SID from an account name.
  11. 3. Call LsaAddAccountRights() to grant privileges to the user(s)
  12.    represented by the supplied SID.
  13. 4. Call LsaRemoveAccountRights() to revoke privileges from the user(s)
  14.    represented by the supplied SID.
  15. 5. Close the policy with LsaClose().
  16. To successfully grant and revoke privileges, the caller needs to be an
  17. administrator on the target system.
  18. The LSA API LsaEnumerateAccountRights() can be used to determine which
  19. privileges have been granted to an account.
  20. The LSA API LsaEnumerateAccountsWithUserRight() can be used to determine
  21. which accounts have been granted a specified privilege.
  22. Documentation and header files for these LSA APIs is provided in the
  23. Windows 32 SDK in the MSTOOLSSECURITY directory.
  24. NOTE: These LSA APIs are currently implemented as Unicode only.
  25. This sample will grant the privilege SeServiceLogonRight to the account
  26. specified on argv[1].
  27. This sample is dependant on these import libs
  28.    advapi32.lib (for LsaXxx)
  29.    user32.lib (for wsprintf)
  30. This sample will work properly compiled ANSI or Unicode.
  31. You can use domainaccount as argv[1]. For instance, mydomainscott will
  32. grant the privilege to the mydomain domain account scott.
  33. The optional target machine is specified as argv[2], otherwise, the
  34. account database is updated on the local machine.
  35. The LSA APIs used by this sample are Unicode only.
  36. Use LsaRemoveAccountRights() to remove account rights.
  37. Scott Field (sfield)    12-Jul-95
  38. --*/
  39. #ifndef UNICODE
  40. #define UNICODE
  41. #endif // UNICODE
  42. #include <windows.h>
  43. #include <stdio.h>
  44. #include "ntsecapi.h"
  45. NTSTATUS
  46. OpenPolicy(
  47.     LPWSTR ServerName,          // machine to open policy on (Unicode)
  48.     DWORD DesiredAccess,        // desired access to policy
  49.     PLSA_HANDLE PolicyHandle    // resultant policy handle
  50.     );
  51. BOOL
  52. GetAccountSid(
  53.     LPTSTR SystemName,          // where to lookup account
  54.     LPTSTR AccountName,         // account of interest
  55.     PSID *Sid                   // resultant buffer containing SID
  56.     );
  57. NTSTATUS
  58. SetPrivilegeOnAccount(
  59.     LSA_HANDLE PolicyHandle,    // open policy handle
  60.     PSID AccountSid,            // SID to grant privilege to
  61.     LPWSTR PrivilegeName,       // privilege to grant (Unicode)
  62.     BOOL bEnable                // enable or disable
  63.     );
  64. void
  65. InitLsaString(
  66.     PLSA_UNICODE_STRING LsaString, // destination
  67.     LPWSTR String                  // source (Unicode)
  68.     );
  69. void
  70. DisplayNtStatus(
  71.     LPSTR szAPI,                // pointer to function name (ANSI)
  72.     NTSTATUS Status             // NTSTATUS error value
  73.     );
  74. void
  75. DisplayWinError(
  76.     LPSTR szAPI,                // pointer to function name (ANSI)
  77.     DWORD WinError              // DWORD WinError
  78.     );
  79. #define RTN_OK 0
  80. #define RTN_USAGE 1
  81. #define RTN_ERROR 13
  82. //
  83. // If you have the ddk, include ntstatus.h.
  84. //
  85. #ifndef STATUS_SUCCESS
  86. #define STATUS_SUCCESS  ((NTSTATUS)0x00000000L)
  87. #endif
  88. int _cdecl
  89. main(int argc, char *argv[])
  90. {
  91.     LSA_HANDLE PolicyHandle;
  92.     WCHAR wComputerName[256]=L"";   // static machine name buffer
  93.     TCHAR AccountName[256];         // static account name buffer
  94.     PSID pSid;
  95.     NTSTATUS Status;
  96.     int iRetVal=RTN_ERROR;          // assume error from main
  97.     if(argc == 1)
  98.     {
  99.         fprintf(stderr,"Usage: %s <Account> [TargetMachine]n",
  100.             argv[0]);
  101.         return RTN_USAGE;
  102.     }
  103.     //
  104.     // Pick up account name on argv[1].
  105.     // Assumes source is ANSI. Resultant string is ANSI or Unicode
  106.     //
  107.     wsprintf(AccountName, TEXT("%hS"), argv[1]);
  108.     //
  109.     // Pick up machine name on argv[2], if appropriate
  110.     // assumes source is ANSI. Resultant string is Unicode.
  111.     //
  112.     if(argc == 3) wsprintfW(wComputerName, L"%hS", argv[2]);
  113.     //
  114.     // Open the policy on the target machine.
  115.     //
  116.     if((Status=OpenPolicy(
  117.                 wComputerName,      // target machine
  118.                 POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
  119.                 &PolicyHandle       // resultant policy handle
  120.                 )) != STATUS_SUCCESS) {
  121.         DisplayNtStatus("OpenPolicy", Status);
  122.         return RTN_ERROR;
  123.     }
  124.     //
  125.     // Obtain the SID of the user/group.
  126.     // Note that we could target a specific machine, but we don't.
  127.     // Specifying NULL for target machine searches for the SID in the
  128.     // following order: well-known, Built-in and local, primary domain,
  129.     // trusted domains.
  130.     //
  131.     if(GetAccountSid(
  132.             NULL,       // default lookup logic
  133.             AccountName,// account to obtain SID
  134.             &pSid       // buffer to allocate to contain resultant SID
  135.             )) {
  136.         //
  137.         // We only grant the privilege if we succeeded in obtaining the
  138.         // SID. We can actually add SIDs which cannot be looked up, but
  139.         // looking up the SID is a good sanity check which is suitable for
  140.         // most cases.
  141.         //
  142.         // Grant the SeServiceLogonRight to users represented by pSid.
  143.         //
  144.         if((Status=SetPrivilegeOnAccount(
  145.                     PolicyHandle,           // policy handle
  146.                     pSid,                   // SID to grant privilege
  147.                     L"SeServiceLogonRight", // Unicode privilege
  148.                     TRUE                    // enable the privilege
  149.                     )) == STATUS_SUCCESS)
  150.             iRetVal=RTN_OK;
  151.         else
  152.             DisplayNtStatus("AddUserRightToAccount", Status);
  153.     }
  154.     else {
  155.         //
  156.         // Error obtaining SID.
  157.         //
  158.         DisplayWinError("GetAccountSid", GetLastError());
  159.     }
  160.     //
  161.     // Close the policy handle.
  162.     //
  163.     LsaClose(PolicyHandle);
  164.     //
  165.     // Free memory allocated for SID.
  166.     //
  167.     if(pSid != NULL) HeapFree(GetProcessHeap(), 0, pSid);
  168.     return iRetVal;
  169. }
  170. void
  171. InitLsaString(
  172.     PLSA_UNICODE_STRING LsaString,
  173.     LPWSTR String
  174.     )
  175. {
  176.     DWORD StringLength;
  177.     if (String == NULL) {
  178.         LsaString->Buffer = NULL;
  179.         LsaString->Length = 0;
  180.         LsaString->MaximumLength = 0;
  181.         return;
  182.     }
  183.     StringLength = wcslen(String);
  184.     LsaString->Buffer = String;
  185.     LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
  186.     LsaString->MaximumLength=(USHORT)(StringLength+1) * sizeof(WCHAR);
  187. }
  188. NTSTATUS
  189. OpenPolicy(
  190.     LPWSTR ServerName,
  191.     DWORD DesiredAccess,
  192.     PLSA_HANDLE PolicyHandle
  193.     )
  194. {
  195.     LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  196.     LSA_UNICODE_STRING ServerString;
  197.     PLSA_UNICODE_STRING Server = NULL;
  198.     //
  199.     // Always initialize the object attributes to all zeroes.
  200.     //
  201.     ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
  202.     if (ServerName != NULL) {
  203.         //
  204.         // Make a LSA_UNICODE_STRING out of the LPWSTR passed in
  205.         //
  206.         InitLsaString(&ServerString, ServerName);
  207.         Server = &ServerString;
  208.     }
  209.     //
  210.     // Attempt to open the policy.
  211.     //
  212.     return LsaOpenPolicy(
  213.                 Server,
  214.                 &ObjectAttributes,
  215.                 DesiredAccess,
  216.                 PolicyHandle
  217.                 );
  218. }
  219. /*++
  220. This function attempts to obtain a SID representing the supplied
  221. account on the supplied system.
  222. If the function succeeds, the return value is TRUE. A buffer is
  223. allocated which contains the SID representing the supplied account.
  224. This buffer should be freed when it is no longer needed by calling
  225. HeapFree(GetProcessHeap(), 0, buffer)
  226. If the function fails, the return value is FALSE. Call GetLastError()
  227. to obtain extended error information.
  228. Scott Field (sfield)    12-Jul-95
  229. --*/
  230. BOOL
  231. GetAccountSid(
  232.     LPTSTR SystemName,
  233.     LPTSTR AccountName,
  234.     PSID *Sid
  235.     )
  236. {
  237.     LPTSTR ReferencedDomain=NULL;
  238.     DWORD cbSid=128;    // initial allocation attempt
  239.     DWORD cbReferencedDomain=16; // initial allocation size
  240.     SID_NAME_USE peUse;
  241.     BOOL bSuccess=FALSE; // assume this function will fail
  242.     __try {
  243.     //
  244.     // initial memory allocations
  245.     //
  246.     if((*Sid=HeapAlloc(
  247.                     GetProcessHeap(),
  248.                     0,
  249.                     cbSid
  250.                     )) == NULL) __leave;
  251.     if((ReferencedDomain=HeapAlloc(
  252.                     GetProcessHeap(),
  253.                     0,
  254.                     cbReferencedDomain
  255.                     )) == NULL) __leave;
  256.     //
  257.     // Obtain the SID of the specified account on the specified system.
  258.     //
  259.     while(!LookupAccountName(
  260.                     SystemName,         // machine to lookup account on
  261.                     AccountName,        // account to lookup
  262.                     *Sid,               // SID of interest
  263.                     &cbSid,             // size of SID
  264.                     ReferencedDomain,   // domain account was found on
  265.                     &cbReferencedDomain,
  266.                     &peUse
  267.                     )) {
  268.         if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  269.             //
  270.             // reallocate memory
  271.             //
  272.             if((*Sid=HeapReAlloc(
  273.                         GetProcessHeap(),
  274.                         0,
  275.                         *Sid,
  276.                         cbSid
  277.                         )) == NULL) __leave;
  278.             if((ReferencedDomain=HeapReAlloc(
  279.                         GetProcessHeap(),
  280.                         0,
  281.                         ReferencedDomain,
  282.                         cbReferencedDomain
  283.                         )) == NULL) __leave;
  284.         }
  285.         else __leave;
  286.     }
  287.     //
  288.     // Indicate success.
  289.     //
  290.     bSuccess=TRUE;
  291.     } // finally
  292.     __finally {
  293.     //
  294.     // Cleanup and indicate failure, if appropriate.
  295.     //
  296.     HeapFree(GetProcessHeap(), 0, ReferencedDomain);
  297.     if(!bSuccess) {
  298.         if(*Sid != NULL) {
  299.             HeapFree(GetProcessHeap(), 0, *Sid);
  300.             *Sid = NULL;
  301.         }
  302.     }
  303.     } // finally
  304.     return bSuccess;
  305. }
  306. NTSTATUS
  307. SetPrivilegeOnAccount(
  308.     LSA_HANDLE PolicyHandle,    // open policy handle
  309.     PSID AccountSid,            // SID to grant privilege to
  310.     LPWSTR PrivilegeName,       // privilege to grant (Unicode)
  311.     BOOL bEnable                // enable or disable
  312.     )
  313. {
  314.     LSA_UNICODE_STRING PrivilegeString;
  315.     //
  316.     // Create a LSA_UNICODE_STRING for the privilege name.
  317.     //
  318.     InitLsaString(&PrivilegeString, PrivilegeName);
  319.     //
  320.     // grant or revoke the privilege, accordingly
  321.     //
  322.     if(bEnable) {
  323.         return LsaAddAccountRights(
  324.                 PolicyHandle,       // open policy handle
  325.                 AccountSid,         // target SID
  326.                 &PrivilegeString,   // privileges
  327.                 1                   // privilege count
  328.                 );
  329.     }
  330.     else {
  331.         return LsaRemoveAccountRights(
  332.                 PolicyHandle,       // open policy handle
  333.                 AccountSid,         // target SID
  334.                 FALSE,              // do not disable all rights
  335.                 &PrivilegeString,   // privileges
  336.                 1                   // privilege count
  337.                 );
  338.     }
  339. }
  340. void
  341. DisplayNtStatus(
  342.     LPSTR szAPI,
  343.     NTSTATUS Status
  344.     )
  345. {
  346.     //
  347.     // Convert the NTSTATUS to Winerror. Then call DisplayWinError().
  348.     //
  349.     DisplayWinError(szAPI, LsaNtStatusToWinError(Status));
  350. }
  351. void
  352. DisplayWinError(
  353.     LPSTR szAPI,
  354.     DWORD WinError
  355.     )
  356. {
  357.     LPSTR MessageBuffer;
  358.     DWORD dwBufferLength;
  359.     //
  360.     // TODO: Get this fprintf out of here!
  361.     //
  362.     fprintf(stderr,"%s error!n", szAPI);
  363.     if(dwBufferLength=FormatMessageA(
  364.                         FORMAT_MESSAGE_ALLOCATE_BUFFER |
  365.                         FORMAT_MESSAGE_FROM_SYSTEM,
  366.                         NULL,
  367.                         WinError,
  368.                         GetUserDefaultLangID(),
  369.                         (LPSTR) &MessageBuffer,
  370.                         0,
  371.                         NULL
  372.                         ))
  373.     {
  374.         DWORD dwBytesWritten; // unused
  375.         //
  376.         // Output message string on stderr.
  377.         //
  378.         WriteFile(
  379.             GetStdHandle(STD_ERROR_HANDLE),
  380.             MessageBuffer,
  381.             dwBufferLength,
  382.             &dwBytesWritten,
  383.             NULL
  384.             );
  385.         //
  386.         // Free the buffer allocated by the system.
  387.         //
  388.         LocalFree(MessageBuffer);
  389.     }
  390. }