Click here to Skip to main content
11,716,938 members (80,497 online)
Click here to Skip to main content

LSA Functions - Privileges and Impersonation

, 27 Aug 2003 CPOL 163K 2.8K 62
Rate this:
Please Sign up or sign in to vote.
Managing privileges and impersonating users


Sometimes you want your application to do things which the user himself may never do. For example, your application has to read a public folder on an exchange server, but the folder is hidden from the active user for good reasons. Now you need LSA functions, to manage privileges and impersonate another user. This article explains how to import the LSA functions, add rights to accounts and impersonate different users.

SIDs, Policies and Rights

Whenever you alter the privileges of an account, you need its Security Identifier (SID). You can find any account using LookupAccountName.

[DllImport( "advapi32.dll", CharSet=CharSet.Auto, 
    SetLastError=true, PreserveSig=true)]
private static extern bool LookupAccountName( 
    string lpSystemName, string lpAccountName, 
    IntPtr psid, ref int cbsid, 
    StringBuilder domainName, ref int cbdomainLength, 
    ref int use ); 

Before adding  or removing any privileges, we need a policy handle. LsaOpenPolicy opens a handle:

[DllImport("advapi32.dll", PreserveSig=true)]
private static extern UInt32 LsaOpenPolicy(
    ref LSA_UNICODE_STRING SystemName,
    ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
    Int32 DesiredAccess,
    out IntPtr PolicyHandle ); 

Using the SID and the policy handle, LsaAddAccountRights can add privileges:

[DllImport("advapi32.dll", SetLastError=true, PreserveSig=true)]
private static extern long LsaAddAccountRights(
    IntPtr PolicyHandle, IntPtr AccountSid, 
    LSA_UNICODE_STRING[] UserRights,
    long CountOfRights ); 

The LSA functions work with Unicode strings, so we have to use the LSA_UNICODE_STRING structure. This structure contains a buffer for the string, an two integers for the length of the buffer and the length of the actual string in the buffer:

private struct LSA_UNICODE_STRING 
  public UInt16 Length; 
  public UInt16 MaximumLength; 
  public IntPtr Buffer; 

Now it's time to call these functions. First, find the desired account and retrieve the SID.

//pointer an size for the SID
IntPtr sid = IntPtr.Zero;
int sidSize = 0; 

//StringBuilder and size for the domain name
StringBuilder domainName = new StringBuilder();
int nameSize = 0;

//account-type variable for lookup
int accountType = 0; 

//get required buffer size
LookupAccountName(String.Empty, accountName, sid, ref sidSize, 
    domainName, ref nameSize, ref accountType); 

//allocate buffers
domainName = new StringBuilder(nameSize);
sid = Marshal.AllocHGlobal(sidSize);

//lookup the SID for the account
bool result = LookupAccountName(String.Empty, accountName, sid, 
    ref sidSize, domainName, ref nameSize, ref accountType); 

And secondly, open a policy handle.

//initialize an empty unicode-string

//initialize a pointer for the policy handle
IntPtr policyHandle = IntPtr.Zero; 

//these attributes are not used, but LsaOpenPolicy 
//wants them to exists

//get a policy handle
uint resultPolicy = LsaOpenPolicy(ref systemName, ref ObjectAttributes, 
    access, out policyHandle);

And finally we are ready to add privileges.

//initialize an unicode-string for the privilege name
userRights[0] = new LSA_UNICODE_STRING(); 
userRights[0].Buffer = Marshal.StringToHGlobalUni(privilegeName); 
userRights[0].Length = (UInt16)( privilegeName.Length * 
    UnicodeEncoding.CharSize ); 
userRights[0].MaximumLength = (UInt16)( (privilegeName.Length+1) * 
    UnicodeEncoding.CharSize );

//add the privilege to the account 
long res = LsaAddAccountRights(policyHandle, sid, userRights, 1);
winErrorCode = LsaNtStatusToWinError(res); 
if(winErrorCode != 0)
    Console.WriteLine("LsaAddAccountRights failed: "+ winErrorCode); 
//close all handles 

More LSA

Now we can manage user's privileges - but how about being another user? LSA includes a set of functions to impersonate any user. This means, performing an invisible logon an switch between our own identity and the new one.

For example, if you're writing a service and you don't get along with network access of the local service authority, you can define a special domain account for your service and impersonate it at runtime. LogonUser is the function to authenticate a user against a domain:

private static extern bool LogonUser( 
    String lpszUsername, 
    String lpszDomain, 
    String lpszPassword, 
    int dwLogonType, 
    int dwLogonProvider, 
    ref IntPtr phToken );

LogonUser verifies the logon parameters an creates a security token. Whenever a user logs onto a workstation, a security token is created. All applications launched by this user hold a copy of this token. He have to copy our new token using DuplicateToken.

private static extern bool DuplicateToken( 
    IntPtr ExistingTokenHandle, 
    int ImpersonationLevel, 
    ref IntPtr DuplicateTokenHandle );

Now we got a copy of the security token, we can create a WindowsIdentity and impersonate the user. The .NET framework contains classes for impersonating users, once we got the right token.

using System.Security.Principal;
WindowsIdentity newId = new WindowsIdentity(duplicateTokenHandle);
WindowsImpersonationContext impersonatedUser = newId.Impersonate();

Of course we have to free the handles at last.

if (existingTokenHandle != IntPtr.Zero)
if (duplicateTokenHandle != IntPtr.Zero)

When we have finished the special tasks, we can switch back to our normal identity


Using the code

In the LogonDemo project there are LsaUtility.cs and LogonUtility.cs. LsaUtility.cs imports the functions necessary for managing privileges and contains the static method SetRight (String accountName, String privilegeName). It adds a named privilege to an account. LogonUtility.cs contains everything you need to impersonate a user.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Corinna John
Software Developer
Germany Germany
Corinna lives in Hannover/Germany (CeBIT City) and works as a Delphi developer, though her favorite language is C#.

You may also be interested in...

Comments and Discussions

QuestionProblems when running this code on Microsoft Server 2012 Pin
Uittenhove18-May-15 22:10
memberUittenhove18-May-15 22:10 
AnswerRe: Problems when running this code on Microsoft Server 2012 Pin
Uittenhove21-May-15 2:18
memberUittenhove21-May-15 2:18 
QuestionHow to use it in windows 8.1 Pin
er.prakash.bhatta28-Oct-14 22:14
memberer.prakash.bhatta28-Oct-14 22:14 
QuestionMassively Helpful Pin
golyaht2-Aug-13 10:56
membergolyaht2-Aug-13 10:56 
QuestionChceck "SeServiceLogonRight already" exist or not for user? Pin
ankyshah26-Jan-11 20:06
memberankyshah26-Jan-11 20:06 
GeneralNice article, even if there are some errors. Pin
iq-man29-Nov-09 22:09
memberiq-man29-Nov-09 22:09 
GeneralRe: Nice article, even if there are some errors. Pin
alexdresko23-Dec-09 8:37
memberalexdresko23-Dec-09 8:37 
GeneralRe: Nice article, even if there are some errors. Pin
iq-man26-Dec-09 2:11
memberiq-man26-Dec-09 2:11 
GeneralRe: Nice article, even if there are some errors. Pin
alexdresko26-Dec-09 7:21
memberalexdresko26-Dec-09 7:21 
GeneralA bit messy... Pin
Jecho Jekov12-Jun-09 9:35
memberJecho Jekov12-Jun-09 9:35 
GeneralRe: A bit messy... Pin
Mark Richards27-Mar-12 5:24
memberMark Richards27-Mar-12 5:24 
QuestionError adding "Logon As Service" right to User Account Pin
sullivrp2-Jun-09 7:00
membersullivrp2-Jun-09 7:00 
AnswerRe: Error adding "Logon As Service" right to User Account Pin
sullivrp3-Jun-09 8:48
membersullivrp3-Jun-09 8:48 
GeneralRe: Error adding "Logon As Service" right to User Account Pin
Corinna John3-Jun-09 9:14
memberCorinna John3-Jun-09 9:14 
GeneralRe: Error adding "Logon As Service" right to User Account Pin
sullivrp3-Jun-09 10:22
membersullivrp3-Jun-09 10:22 
GeneralRe: Error adding "Logon As Service" right to User Account Pin
Corinna John3-Jun-09 10:51
memberCorinna John3-Jun-09 10:51 
GeneralRe: Error adding "Logon As Service" right to User Account Pin
sullivrp4-Jun-09 5:39
membersullivrp4-Jun-09 5:39 
AnswerRe: Error adding "Logon As Service" right to User Account Pin
ankyshah26-Jan-11 20:08
memberankyshah26-Jan-11 20:08 
Questionhow give user'privilege to a programm ? Pin
vincent3120-Oct-06 6:45
membervincent3120-Oct-06 6:45 
AnswerRe: how give user'privilege to a programm ? Pin
vincent3120-Oct-06 7:57
membervincent3120-Oct-06 7:57 
GeneralLsaNtStatusToWinError work incorect. Pin
Seregil15-Jun-06 1:02
memberSeregil15-Jun-06 1:02 
GeneralChanging Domain Group Policy Pin
Scott S.22-May-06 5:29
memberScott S.22-May-06 5:29 

Its nice to run across articles that remain relevant long after they were written ... good one!

I am attempting to update an existing VB6 application that automates a very involved installation of a server product. It creates user accounts, groups, files, file shares, DCOM components, and COM+ applications and proxies, etc.
It works just fine in work groups and in Win2k domains, but in a Windows 2003 domain the server only runs for a little while after installation.

I determined that it is because during the installation of the COM+ application, the account used as it's identity is implicitly set into the local security policy with the "Log on as batch job" privilege. But in the W2003 domain the overriding global policy proceeds to write over that change to local policy. Seems to do it periodically even without the system restarting.

Anyway, I wanted to know if I could use these calls to give the server's identity account the "Log on a batch job" privilege in the domains Global Policy for Local Security Settings? And it so, what would the calls look like parameter wise? I shouldn't have any trouble porting sample code to VB6 even though I'm a C/C++/C# guy.

QuestionImpersonation??? Pin
tee_jay23-Mar-06 7:46
membertee_jay23-Mar-06 7:46 
AnswerRe: Impersonation??? Pin
Scott S.22-May-06 5:14
memberScott S.22-May-06 5:14 
GeneralLsaOpenPolicy Error...again Pin
mr24shoe20-Mar-06 12:22
membermr24shoe20-Mar-06 12:22 
GeneralRe: LsaOpenPolicy Error...again Pin
Jecho Jekov12-Jun-09 9:37
memberJecho Jekov12-Jun-09 9:37 
GeneralVery good job Pin
segelfix19-Mar-06 10:48
membersegelfix19-Mar-06 10:48 
GeneralImpersonation - Console App - SAMBA Pin
lucasfong6-Jan-05 10:55
memberlucasfong6-Jan-05 10:55 
GeneralLsaOpenPolicy Error Pin
Kermittt15-Sep-04 20:42
memberKermittt15-Sep-04 20:42 
GeneralRe: LsaOpenPolicy Error Pin
gav_jackson5-Jan-05 4:24
membergav_jackson5-Jan-05 4:24 
GeneralRe: LsaOpenPolicy Error Pin
Kermittt5-Jan-05 11:58
memberKermittt5-Jan-05 11:58 
GeneralRe: LsaOpenPolicy Error Pin
gav_jackson5-Jan-05 21:59
membergav_jackson5-Jan-05 21:59 
GeneralRe: LsaOpenPolicy Error Pin
Kermittt6-Jan-05 11:49
memberKermittt6-Jan-05 11:49 
GeneralRe: LsaOpenPolicy Error Pin
Tokus17-Jul-06 8:53
memberTokus17-Jul-06 8:53 
GeneralRe: LsaOpenPolicy Error Pin
neotussanonis24-May-07 13:13
memberneotussanonis24-May-07 13:13 
QuestionUndocumented Lsa* Functions?? Pin
Dan Madden26-Aug-04 6:49
memberDan Madden26-Aug-04 6:49 
AnswerRe: Undocumented Lsa* Functions?? Pin
Corinna John29-Aug-04 1:19
memberCorinna John29-Aug-04 1:19 
Generalquestion Pin
lwcotton91917-Aug-04 23:28
memberlwcotton91917-Aug-04 23:28 
AnswerRe: question Pin
tee_jay23-Mar-06 7:43
membertee_jay23-Mar-06 7:43 
GeneralAppDomain Impersonation Pin
chriskoiak16-Mar-04 0:27
memberchriskoiak16-Mar-04 0:27 
GeneralRe: AppDomain Impersonation Pin
mjesterak25-Jan-06 18:33
membermjesterak25-Jan-06 18:33 
GeneralSID Retrieving Pin
smidz11-Feb-04 5:50
membersmidz11-Feb-04 5:50 
GeneralRe: SID Retrieving Pin
Dan Madden26-Aug-04 6:35
memberDan Madden26-Aug-04 6:35 
GeneralImpersonation Pin
DidactSoft23-Jan-04 21:22
memberDidactSoft23-Jan-04 21:22 
GeneralRe: Impersonation Pin
Corinna John24-Jan-04 1:25
memberCorinna John24-Jan-04 1:25 
GeneralError When Trying to Impersonate Against the Domain Pin
frosty86753094-Sep-03 9:45
memberfrosty86753094-Sep-03 9:45 
GeneralRe: Error When Trying to Impersonate Against the Domain Pin
Corinna John4-Sep-03 10:27
memberCorinna John4-Sep-03 10:27 
GeneralRe: Error When Trying to Impersonate Against the Domain Pin
frosty86753094-Sep-03 11:25
memberfrosty86753094-Sep-03 11:25 
GeneralRe: Error When Trying to Impersonate Against the Domain Pin
Corinna John4-Sep-03 19:16
memberCorinna John4-Sep-03 19:16 
GeneralRe: Error When Trying to Impersonate Against the Domain Pin
frosty86753095-Sep-03 4:53
memberfrosty86753095-Sep-03 4:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150901.1 | Last Updated 28 Aug 2003
Article Copyright 2003 by Corinna John
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid