如何管理以编程方式在 Windows NT 中的用户权限(C 语言)
http://www.cnblogs.com/bluesky_blog/archive/2009/04/29.html
管理用户权限可以实现以编程方式使用下列步骤:
LSA API LsaEnumerateAccountRights() 可确定已授予的权限的帐户。
LSA API LsaEnumerateAccountsWithUserRight() 可确定哪些帐户已被授予指定的权限。
MSTOOLS\SECURITY 目录中 Windows 32 SDK 中提供的这些 LSA API 的文档和头文件。
在 Win32 SDK 的最新版本中, 邮件头显示在 mstools\samples\win32\winnt\security\include 目录中且文档处于正在 \security\lsasamp\lsaapi.hlp。
注意: 这些 LSA API 是当前实现以 Unicode 格式仅。
本示例将授予特权 SeServiceLogonRight 为 argv [1] 上指定的帐户。
此示例是依赖于这些导入库
管理用户权限可以实现以编程方式使用下列步骤:
- 打开与 LsaOpenPolicy() 的目标计算机上的策略。 要授予的权限,打开 POLICY_CREATE_ACCOUNT 和 POLICY_LOOKUP_NAMES 访问策略。 若要吊销权限,打开 POLICY_LOOKUP_NAMES 访问策略。
- 获取一个 SID (安全标识符),表示用户 / 组感兴趣。 LookupAccountName() 和 LsaLookupNames() API 可以从一个帐户名获取 SID。
- 调用 LsaAddAccountRights() 向由提供的 SID 的用户授予特权。
- 调用 LsaRemoveAccountRights() 撤消由提供的 SID 的用户权限。
- 关闭该策略与 LsaClose()。
LSA API LsaEnumerateAccountRights() 可确定已授予的权限的帐户。
LSA API LsaEnumerateAccountsWithUserRight() 可确定哪些帐户已被授予指定的权限。
MSTOOLS\SECURITY 目录中 Windows 32 SDK 中提供的这些 LSA API 的文档和头文件。
在 Win32 SDK 的最新版本中, 邮件头显示在 mstools\samples\win32\winnt\security\include 目录中且文档处于正在 \security\lsasamp\lsaapi.hlp。
注意: 这些 LSA API 是当前实现以 Unicode 格式仅。
本示例将授予特权 SeServiceLogonRight 为 argv [1] 上指定的帐户。
此示例是依赖于这些导入库
advapi32.lib (对于 LsaXxx)
user32.lib (对于 wsprintf)
本示例将工作正确编译 ANSI 或 Unicode。
user32.lib (对于 wsprintf)
回到顶端
示例代码
1 /**/ /*++
2You can use domain\account as argv[1]. For instance, mydomain\scott will
3grant the privilege to the mydomain domain account scott.
4The optional target machine is specified as argv[2], otherwise, the
5account database is updated on the local machine.
6The LSA APIs used by this sample are Unicode only.
7Use LsaRemoveAccountRights() to remove account rights.
8Scott Field (sfield) 12-Jul-95
9--*/
10 #ifndef UNICODE
11 #define UNICODE
12 #endif // UNICODE
13 #include < windows.h >
14 #include < stdio.h >
15 #include " ntsecapi.h "
16 NTSTATUS
17 OpenPolicy(
18 LPWSTR ServerName, // machine to open policy on (Unicode)
19 DWORD DesiredAccess, // desired access to policy
20 PLSA_HANDLE PolicyHandle // resultant policy handle
21 );
22 BOOL
23 GetAccountSid(
24 LPTSTR SystemName, // where to lookup account
25 LPTSTR AccountName, // account of interest
26 PSID * Sid // resultant buffer containing SID
27 );
28 NTSTATUS
29 SetPrivilegeOnAccount(
30 LSA_HANDLE PolicyHandle, // open policy handle
31 PSID AccountSid, // SID to grant privilege to
32 LPWSTR PrivilegeName, // privilege to grant (Unicode)
33 BOOL bEnable // enable or disable
34 );
35 void
36 InitLsaString(
37 PLSA_UNICODE_STRING LsaString, // destination
38 LPWSTR String // source (Unicode)
39 );
40 void
41 DisplayNtStatus(
42 LPSTR szAPI, // pointer to function name (ANSI)
43 NTSTATUS Status // NTSTATUS error value
44 );
45 void
46 DisplayWinError(
47 LPSTR szAPI, // pointer to function name (ANSI)
48 DWORD WinError // DWORD WinError
49 );
50 #define RTN_OK 0
51 #define RTN_USAGE 1
52 #define RTN_ERROR 13
53 //
54 // If you have the ddk, include ntstatus.h.
55 //
56 #ifndef STATUS_SUCCESS
57 #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
58 #endif
59 int _cdecl
60 main( int argc, char * argv[])
61 {
62LSA_HANDLE PolicyHandle;
63WCHAR wComputerName[256]=L""; // static machine name buffer
64TCHAR AccountName[256]; // static account name buffer
65PSID pSid;
66NTSTATUS Status;
67int iRetVal=RTN_ERROR; // assume error from main
68if(argc == 1)
69{
70fprintf(stderr,"Usage: %s <Account> [TargetMachine]\n",
71argv[0]);
72return RTN_USAGE;
73}
74//
75// Pick up account name on argv[1].
76// Assumes source is ANSI. Resultant string is ANSI or Unicode
77//
78wsprintf(AccountName, TEXT("%hS"), argv[1]);
79//
80// Pick up machine name on argv[2], if appropriate
81// assumes source is ANSI. Resultant string is Unicode.
82//
83if(argc == 3) wsprintfW(wComputerName, L"%hS", argv[2]);
84//
85// Open the policy on the target machine.
86//
87if((Status=OpenPolicy(
88wComputerName, // target machine
89POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
90&PolicyHandle // resultant policy handle
91)) != STATUS_SUCCESS) {
92DisplayNtStatus("OpenPolicy", Status);
93return RTN_ERROR;
94}
95//
96// Obtain the SID of the user/group.
97// Note that we could target a specific machine, but we don't.
98// Specifying NULL for target machine searches for the SID in the
99// following order: well-known, Built-in and local, primary domain,
100// trusted domains.
101//
102if(GetAccountSid(
103NULL, // default lookup logic
104AccountName,// account to obtain SID
105&pSid // buffer to allocate to contain resultant SID
106)) {
107//
108// We only grant the privilege if we succeeded in obtaining the
109// SID. We can actually add SIDs which cannot be looked up, but
110// looking up the SID is a good sanity check which is suitable for
111// most cases.
112//
113// Grant the SeServiceLogonRight to users represented by pSid.
114//
115if((Status=SetPrivilegeOnAccount(
116PolicyHandle, // policy handle
117pSid, // SID to grant privilege
118L"SeServiceLogonRight", // Unicode privilege
119TRUE // enable the privilege
120)) == STATUS_SUCCESS)
121iRetVal=RTN_OK;
122else
123DisplayNtStatus("AddUserRightToAccount", Status);
124}
125else {
126//
127// Error obtaining SID.
128//
129DisplayWinError("GetAccountSid", GetLastError());
130}
131//
132// Close the policy handle.
133//
134LsaClose(PolicyHandle);
135//
136// Free memory allocated for SID.
137//
138if(pSid != NULL) HeapFree(GetProcessHeap(), 0, pSid);
139return iRetVal;
140}
141 void
142 InitLsaString(
143 PLSA_UNICODE_STRING LsaString,
144 LPWSTR String
145 )
146 {
147DWORD StringLength;
148if (String == NULL) {
149LsaString->Buffer = NULL;
150LsaString->Length = 0;
151LsaString->MaximumLength = 0;
152return;
153}
154StringLength = wcslen(String);
155LsaString->Buffer = String;
156LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
157LsaString->MaximumLength=(USHORT)(StringLength+1) * sizeof(WCHAR);
158}
159 NTSTATUS
160 OpenPolicy(
161 LPWSTR ServerName,
162 DWORD DesiredAccess,
163 PLSA_HANDLE PolicyHandle
164 )
165 {
166LSA_OBJECT_ATTRIBUTES ObjectAttributes;
167LSA_UNICODE_STRING ServerString;
168PLSA_UNICODE_STRING Server = NULL;
169//
170// Always initialize the object attributes to all zeroes.
171//
172ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
173if (ServerName != NULL) {
174//
175// Make a LSA_UNICODE_STRING out of the LPWSTR passed in
176//
177InitLsaString(&ServerString, ServerName);
178Server = &ServerString;
179}
180//
181// Attempt to open the policy.
182//
183return LsaOpenPolicy(
184Server,
185&ObjectAttributes,
186DesiredAccess,
187PolicyHandle
188);
189}
190 /**/ /*++
191This function attempts to obtain a SID representing the supplied
192account on the supplied system.
193If the function succeeds, the return value is TRUE. A buffer is
194allocated which contains the SID representing the supplied account.
195This buffer should be freed when it is no longer needed by calling
196HeapFree(GetProcessHeap(), 0, buffer)
197If the function fails, the return value is FALSE. Call GetLastError()
198to obtain extended error information.
199Scott Field (sfield) 12-Jul-95
200--*/
201 BOOL
202 GetAccountSid(
203 LPTSTR SystemName,
204 LPTSTR AccountName,
205 PSID * Sid
206 )
207 {
208LPTSTR ReferencedDomain=NULL;
209DWORD cbSid=128; // initial allocation attempt
210DWORD cchReferencedDomain=16; // initial allocation size
211SID_NAME_USE peUse;
212BOOL bSuccess=FALSE; // assume this function will fail
213__try {
214//
215// initial memory allocations
216//
217if((*Sid=HeapAlloc(
218GetProcessHeap(),
2190,
220cbSid
221)) == NULL) __leave;
222if((ReferencedDomain=(LPTSTR)HeapAlloc(
223GetProcessHeap(),
2240,
225cchReferencedDomain * sizeof(TCHAR)
226)) == NULL) __leave;
227//
228// Obtain the SID of the specified account on the specified system.
229//
230while(!LookupAccountName(
231SystemName, // machine to lookup account on
232AccountName, // account to lookup
233*Sid, // SID of interest
234&cbSid, // size of SID
235ReferencedDomain, // domain account was found on
236&cchReferencedDomain,
237&peUse
238)) {
239if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
240//
241// reallocate memory
242//
243if((*Sid=HeapReAlloc(
244GetProcessHeap(),
2450,
246*Sid,
247cbSid
248)) == NULL) __leave;
249if((ReferencedDomain=(LPTSTR)HeapReAlloc(
250GetProcessHeap(),
2510,
252ReferencedDomain,
253cchReferencedDomain * sizeof(TCHAR)
254)) == NULL) __leave;
255}
256else __leave;
257}
258//
259// Indicate success.
260//
261bSuccess=TRUE;
262} // finally
263__finally {
264//
265// Cleanup and indicate failure, if appropriate.
266//
267HeapFree(GetProcessHeap(), 0, ReferencedDomain);
268if(!bSuccess) {
269if(*Sid != NULL) {
270HeapFree(GetProcessHeap(), 0, *Sid);
271*Sid = NULL;
272}
273}
274} // finally
275return bSuccess;
276}
277 NTSTATUS
278 SetPrivilegeOnAccount(
279 LSA_HANDLE PolicyHandle, // open policy handle
280 PSID AccountSid, // SID to grant privilege to
281 LPWSTR PrivilegeName, // privilege to grant (Unicode)
282 BOOL bEnable // enable or disable
283 )
284 {
285LSA_UNICODE_STRING PrivilegeString;
286//
287// Create a LSA_UNICODE_STRING for the privilege name.
288//
289InitLsaString(&PrivilegeString, PrivilegeName);
290//
291// grant or revoke the privilege, accordingly
292//
293if(bEnable) {
294return LsaAddAccountRights(
295PolicyHandle, // open policy handle
296AccountSid, // target SID
297&PrivilegeString, // privileges
2981 // privilege count
299);
300}
301else {
302return LsaRemoveAccountRights(
303PolicyHandle, // open policy handle
304AccountSid, // target SID
305FALSE, // do not disable all rights
306&PrivilegeString, // privileges
3071 // privilege count
308);
309}
310}
311 void
312 DisplayNtStatus(
313 LPSTR szAPI,
314 NTSTATUS Status
315 )
316 {
317//
318// Convert the NTSTATUS to Winerror. Then call DisplayWinError().
319//
320DisplayWinError(szAPI, LsaNtStatusToWinError(Status));
321}
322 void
323 DisplayWinError(
324 LPSTR szAPI,
325 DWORD WinError
326 )
327 {
328LPSTR MessageBuffer;
329DWORD dwBufferLength;
330//
331// TODO: Get this fprintf out of here!
332//
333fprintf(stderr,"%s error!\n", szAPI);
334if(dwBufferLength=FormatMessageA(
335FORMAT_MESSAGE_ALLOCATE_BUFFER |
336FORMAT_MESSAGE_FROM_SYSTEM,
337NULL,
338WinError,
339GetUserDefaultLangID(),
340(LPSTR) &MessageBuffer,
3410,
342NULL
343))
344{
345DWORD dwBytesWritten; // unused
346//
347// Output message string on stderr.
348//
349WriteFile(
350GetStdHandle(STD_ERROR_HANDLE),
351MessageBuffer,
352dwBufferLength,
353&dwBytesWritten,
354NULL
355);
356//
357// Free the buffer allocated by the system.
358//
359LocalFree(MessageBuffer);
360}
361}
362
363 /**/ /*++
364This function enables system access on the account represented by the
365supplied SID. An example of such access is the SeLogonServiceRight.
366Note: to disable a given system access, simply remove the supplied
367access flag from the existing flag, and apply the result to the
368account.
369If the function succeeds, the return value is STATUS_SUCCESS.
370If the function fails, the return value is an NTSTATUS value.
371Scott Field (sfield) 14-Jul-95
372--*/
373 NTSTATUS
374 AddSystemAccessToAccount(
375 LSA_HANDLE PolicyHandle,
376 PSID AccountSid,
377 ULONG NewAccess
378 )
379 {
380LSA_HANDLE AccountHandle;
381ULONG PreviousAccess;
382NTSTATUS Status;
383//
384// open the account object. If it doesn't exist, create a new one
385//
386if((Status=LsaOpenAccount(
387PolicyHandle,
388AccountSid,
389ACCOUNT_ADJUST_SYSTEM_ACCESS | ACCOUNT_VIEW,
390&AccountHandle
391)) == STATUS_OBJECT_NAME_NOT_FOUND)
392{
393Status=LsaCreateAccount(
394PolicyHandle,
395AccountSid,
396ACCOUNT_ADJUST_SYSTEM_ACCESS | ACCOUNT_VIEW,
397&AccountHandle
398);
399}
400//
401// if an error occurred opening or creating, return
402//
403if(Status != STATUS_SUCCESS) return Status;
404//
405// obtain current system access flags
406//
407if((Status=LsaGetSystemAccessAccount(
408AccountHandle,
409&PreviousAccess
410)) == STATUS_SUCCESS)
411{
412//
413// Add the specified access to the account
414//
415Status=LsaSetSystemAccessAccount(
416AccountHandle,
417PreviousAccess | NewAccess
418);
419}
420LsaClose(AccountHandle);
421return Status;
422}
423 /**/ /*++
424This function grants a privilege to the account represented by the
425supplied SID. An example of such a privilege is the
426SeBackupPrivilege.
427Note: To revoke a privilege, use LsaRemovePrivilegesFromAccount.
428If the function succeeds, the return value is STATUS_SUCCESS.
429If the function fails, the return value is an NTSTATUS value.
430Scott Field (sfield) 13-Jul-95
431--*/
432 NTSTATUS
433 AddPrivilegeToAccount(
434 LSA_HANDLE PolicyHandle,
435 PSID AccountSid,
436 LPWSTR PrivilegeName
437 )
438 {
439PRIVILEGE_SET ps;
440LUID_AND_ATTRIBUTES luidattr;
441LSA_HANDLE AccountHandle;
442LSA_UNICODE_STRING PrivilegeString;
443NTSTATUS Status;
444//
445// Create a LSA_UNICODE_STRING for the privilege name
446//
447InitLsaString(&PrivilegeString, PrivilegeName);
448//
449// obtain the LUID of the supplied privilege
450//
451if((Status=LsaLookupPrivilegeValue(
452PolicyHandle,
453&PrivilegeString,
454&luidattr.Luid
455)) != STATUS_SUCCESS) return Status;
456//
457// setup PRIVILEGE_SET
458//
459luidattr.Attributes=0;
460ps.PrivilegeCount=1;
461ps.Control=0;
462ps.Privilege[0]=luidattr;
463//
464// open the account object if it doesn't exist, create a new one
465//
466if((Status=LsaOpenAccount(
467PolicyHandle,
468AccountSid,
469ACCOUNT_ADJUST_PRIVILEGES,
470&AccountHandle
471)) == STATUS_OBJECT_NAME_NOT_FOUND)
472{
473Status=LsaCreateAccount(
474PolicyHandle,
475AccountSid,
476ACCOUNT_ADJUST_PRIVILEGES,
477&AccountHandle
478);
479}
480//
481// if an error occurred opening or creating, return
482//
483if(Status != STATUS_SUCCESS) return Status;
484//
485// add the privileges to the account
486//
487Status=LsaAddPrivilegesToAccount(
488AccountHandle,
489&ps
490);
491LsaClose(AccountHandle);
492return Status;
493}
494
495
转自:http://support.microsoft.com/kb/132958/zh-cn
LSA Functions - Privileges and Impersonation (C#)
http://www.cnblogs.com/bluesky_blog/archive/2009/04/29.html