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

Windows编程

开发平台:

Visual C++

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