WINAMP.COM | Forums : Powered by vBulletin version 2.3.9 WINAMP.COM | Forums > Developer Center > NSIS Discussion > Check a user has a certain permission
  Last Thread   Next Thread
Author
Thread Post New Thread    Post A Reply
RobGrant
Senior Member

Registered: Sep 2004
From: Nottingham

Check a user has a certain permission

Hi guys

Wondered if there's a way to see whether a user has the Logon As Service NT privilege.

I want to grant this privilege if they don't have it (which is easy - if I perform the operation and the user already has the permission the plugin I use - UserMgr - just ignores it). The issue is that I only want to remove that permission in uninstall if they didn't not already have it.

So basically I want to record in the Registry to remove the user privilege only if I added it in the first place!

Any ideas?

Thanks

__________________
-rob-
Winnow Web Design
My blog
Primrose House Bed and Breakfast, Cotgrave, Nottingham

Quick Link | Report this post to a moderator | IP: Logged

RobGrant is offline Old Post 04-04-2006 11:17 AM
Click Here to See the Profile for RobGrant Click here to Send RobGrant a Private Message Visit RobGrant's homepage! Find more posts by RobGrant Add RobGrant to your buddy list Edit/Delete Message Reply w/Quote
kichik
M.I.A.
[NSIS Dev, Mod]

Registered: Oct 2001
From: Israel

You can call LsaEnumerateAccountRights or you can try using this privilege in the installer to see if it's granted already. I don't know of any plug-in that already does that.

__________________
NSIS FAQ | NSIS Home Page | Donate $
"I hear and I forget. I see and I remember. I do and I understand." -- Confucius

Quick Link | Report this post to a moderator | IP: Logged

kichik is offline Old Post 04-04-2006 02:20 PM
Click Here to See the Profile for kichik Click here to Send kichik a Private Message Visit kichik's homepage! Find more posts by kichik Add kichik to your buddy list Edit/Delete Message Reply w/Quote
RobGrant
Senior Member

Registered: Sep 2004
From: Nottingham

Hm, yes I see. That seems reasonably involved, is there anyone with more experience of calling Windows API functions that could have a look at this for me?

This is a useful url.

Thanks

__________________
-rob-
Winnow Web Design
My blog
Primrose House Bed and Breakfast, Cotgrave, Nottingham

Quick Link | Report this post to a moderator | IP: Logged

RobGrant is offline Old Post 04-26-2006 09:35 AM
Click Here to See the Profile for RobGrant Click here to Send RobGrant a Private Message Visit RobGrant's homepage! Find more posts by RobGrant Add RobGrant to your buddy list Edit/Delete Message Reply w/Quote
CancerFace
Senior Member

Registered: Apr 2006
From:

I am also interested in this. It involves allocation of an Lsa policy handle, something which I have been trying to do for a while now without any success, as stated in this thread.
CF

[Edit]
In general this is what you are looking for:

code:
# get the policy handle and place it on R0 !define POLICY_LOOKUP_NAMES 0x00000800 !define strLSA_OBJECT_ATTRIBUTES '(i,i,i,i,i,i)i' System::Call '*${strLSA_OBJECT_ATTRIBUTES}(0,n,n,0,n,n).s' Pop $0 System::Call '*$0${strLSA_OBJECT_ATTRIBUTES}(0,n,n,0,n,n)' ; Fill the structure with zeros System::Call 'kernel32::ZeroMemory(i r0, i 24)' StrCpy $1 ${POLICY_LOOKUP_NAMES} ; Initiallize the policy handle as null StrCpy $R5 "" ; Open the handle and place it in $R0 System::Call 'advapi32::LsaOpenPolicy(w n, i r0, i r1, *i .R0)' # Get the user SID ; Define the UserName StrCpy $2 "$UserName" StrCpy $3 ${NSIS_MAX_STRLEN} ; Allocate memory to accept the SID System::Call '*(&w${NSIS_MAX_STRLEN})i.R4' ; Call the function and place the SID to R1 System::Call 'Advapi32::LookupAccountNameW(w n, w r2, i R1, *i r3, w .R8, *i r3, *i .r4)' # Enumerate the rights ; R2 is the pointer to an array of LSA_UNICODE_STRING structures ; R3 is a variable that receives the number of privileges in the UserRights array System::Call 'advapi32::LsaEnumerateAccountRights(i R0, i R1, *i R2, *i R3)' # close the policy handle System::Call 'advapi32::LsaClose(R0)'
The above code will not work for the LsaOpenPolicy handle and I do not know why. The LsaEnumerateAccountRights function will give you an array of structures that have the format listed here and the trick is to pay attention that the structures accept the sizes in bytes.
Hope this helps as a starting point ...

Last edited by CancerFace on 04-26-2006 at 11:27 AM

Quick Link | Report this post to a moderator | IP: Logged

CancerFace is offline Old Post 04-26-2006 09:53 AM
Click Here to See the Profile for CancerFace Click here to Send CancerFace a Private Message Find more posts by CancerFace Add CancerFace to your buddy list Edit/Delete Message Reply w/Quote
CancerFace
Senior Member

Registered: Apr 2006
From:

If it were not for kitchik's input in this thread I wouldn't be able to write this

Here is what you are looking for:

code:
!define POLICY_LOOKUP_NAMES 0x00000800 !define strLSA_OBJECT_ATTRIBUTES '(i,i,w,i,i,i)i' !define strLSA_UNICODE_STRING '(i,i,w)i' # get the policy handle and place it on R0 System::Call '*${strLSA_OBJECT_ATTRIBUTES}(24,n,n,0,n,n).s' Pop $0 System::Call 'kernel32::ZeroMemory(i r0, i 24)' StrCpy $1 ${POLICY_LOOKUP_NAMES} System::Call 'advapi32::LsaOpenPolicy(w n, i r0, i r1, *i .R0) i.R6' System::Call 'advapi32::LsaNtStatusToWinError(i R6) i.R7' ; R7 should be zero if the call was succesful # Get the user SID and place it on R1 StrCpy $2 "$UserName" ; define this somewhere StrCpy $3 ${NSIS_MAX_STRLEN} System::Call '*(&w${NSIS_MAX_STRLEN})i.R1' System::Call 'Advapi32::LookupAccountNameW(w n, w r2, i R1, *i r3, w .R8, *i r3, *i .r4)' # Enumerate the rights ; R2 is the pointer to an array of LSA_UNICODE_STRING structures ; R3 is a variable that receives the number of privileges in the R2 array System::Call 'advapi32::LsaEnumerateAccountRights(i R0, i R1, *i .R2, *i .R3)i.R6' System::Call 'advapi32::LsaNtStatusToWinError(i R6) i.R7' ; R7 should be zero if the call was succesful # close the policy handle System::Call 'advapi32::LsaClose(i R0)'
$R3 in the above code will hold the number of enumerated privileges in the array found in $R2. You can pull the privilleges out by calling
code:
System::Call '*$R2${strLSA_UNICODE_STRING}(.r1,.r2,.r3)'
for the first structure, then calculate its size, advance to the next buffer ($R2 + size of first structure) and call it again. Repeat $R3 times ... The names of the privilleges are listed in NTSecAPI.h

CF

Quick Link | Report this post to a moderator | IP: Logged

CancerFace is offline Old Post 04-28-2006 10:09 PM
Click Here to See the Profile for CancerFace Click here to Send CancerFace a Private Message Find more posts by CancerFace Add CancerFace to your buddy list Edit/Delete Message Reply w/Quote
RobGrant
Senior Member

Registered: Sep 2004
From: Nottingham

Hmm, thanks for that code, it looks ace, but I'm not sure how to carry on in the way you say. I'm not too au fait with how to finish this off to find the SE_SERVICE_LOGON_NAME privilege.

__________________
-rob-
Winnow Web Design
My blog
Primrose House Bed and Breakfast, Cotgrave, Nottingham

Quick Link | Report this post to a moderator | IP: Logged

RobGrant is offline Old Post 05-05-2006 08:35 AM
Click Here to See the Profile for RobGrant Click here to Send RobGrant a Private Message Visit RobGrant's homepage! Find more posts by RobGrant Add RobGrant to your buddy list Edit/Delete Message Reply w/Quote
CancerFace
Senior Member

Registered: Apr 2006
From:

Between the code that I posted on my previous reply and this MSDN page you should get an idea of what you're after. The definitions of the privileges are found in NTSecAPI.h of the windows SDK. Here are the basic ones straight out of that file:

code:
#define SE_INTERACTIVE_LOGON_NAME TEXT("SeInteractiveLogonRight") #define SE_NETWORK_LOGON_NAME TEXT("SeNetworkLogonRight") #define SE_BATCH_LOGON_NAME TEXT("SeBatchLogonRight") #define SE_SERVICE_LOGON_NAME TEXT("SeServiceLogonRight") #define SE_DENY_INTERACTIVE_LOGON_NAME TEXT("SeDenyInteractiveLogonRight") #define SE_DENY_NETWORK_LOGON_NAME TEXT("SeDenyNetworkLogonRight") #define SE_DENY_BATCH_LOGON_NAME TEXT("SeDenyBatchLogonRight") #define SE_DENY_SERVICE_LOGON_NAME TEXT("SeDenyServiceLogonRight") #define SE_REMOTE_INTERACTIVE_LOGON_NAME TEXT("SeRemoteInteractiveLogonRight") #define SE_DENY_REMOTE_INTERACTIVE_LOGON_NAME TEXT("SeDenyRemoteInteractiveLogonRight")
so if I am reading this right, when you enumerate the privileges, you should end up with an array of LSA_UNICODE_STRING structures and each one contains one privilege, such as SeServiceLogonRight (which is the SE_SERVICE_LOGON_NAME privilege that you're after).

In your case, one of the elements of the array will contain the SeServiceLogonRight privilege so $3 on my last piece of code will be equal to SeServiceLogonRight:
code:
System::Call '*$R2${strLSA_UNICODE_STRING}(.r1,.r2,.r3)'

I'll try to write this up for you as soon as I get some time.

CF

Quick Link | Report this post to a moderator | IP: Logged

CancerFace is offline Old Post 05-05-2006 09:34 AM
Click Here to See the Profile for CancerFace Click here to Send CancerFace a Private Message Find more posts by CancerFace Add CancerFace to your buddy list Edit/Delete Message Reply w/Quote
RobGrant
Senior Member

Registered: Sep 2004
From: Nottingham

Yeah, I'm seeing what you're saying, although I don't think I can yet translate that into what I need for myself. I tried seeing what was in r1, r2 and r3, I think r3 was "1" when the privilege was enabled, and "0" otherwise...don't know if that helps.

Thanks for your help man, you're obviously good at this

__________________
-rob-
Winnow Web Design
My blog
Primrose House Bed and Breakfast, Cotgrave, Nottingham

Quick Link | Report this post to a moderator | IP: Logged

RobGrant is offline Old Post 05-05-2006 09:39 AM
Click Here to See the Profile for RobGrant Click here to Send RobGrant a Private Message Visit RobGrant's homepage! Find more posts by RobGrant Add RobGrant to your buddy list Edit/Delete Message Reply w/Quote
CancerFace
Senior Member

Registered: Apr 2006
From:

quote:
Thanks for your help man, you're obviously good at this
Hey I am glad you think so but unfortunately that's not true

I played around a bit with this today but I was wrong to assume that the LsaEnumerateAccountRights function gives an array of LSA_UNICODE_STRING structures that you could call as I suggested on my previous post (although this is what M$ suggests in its MSDN page)

According to this page the function gives an array but in order to unmarshal it you need to do this:
code:
// QUESTION: Why can't we just use an array of LSAInter.LSA_UNICODE_STRING ??? LSA_UNICODE_STRING right = (LSA_UNICODE_STRING)Marshal.PtrToStructure( (IntPtr)((int)rights + i * Marshal.SizeOf(typeof(LSA_UNICODE_STRING))), typeof(LSA_UNICODE_STRING) ); privileges[i] = Marshal.PtrToStringAuto(right.Buffer,(int)right.Length);

Apparently I was not the only one who thought that we could get the data out using an LSA_UNICODE_STRING array as I suggested

However, I failed to translate the above code to a working NSIS system call. This is where the real pros have to jump into this discussion ...

CF

Quick Link | Report this post to a moderator | IP: Logged

CancerFace is offline Old Post 05-08-2006 08:05 PM
Click Here to See the Profile for CancerFace Click here to Send CancerFace a Private Message Find more posts by CancerFace Add CancerFace to your buddy list Edit/Delete Message Reply w/Quote
RobGrant
Senior Member

Registered: Sep 2004
From: Nottingham

Ah mate, thanks for all your help. Hopefully someone even more experienced than you can help

__________________
-rob-
Winnow Web Design
My blog
Primrose House Bed and Breakfast, Cotgrave, Nottingham

Quick Link | Report this post to a moderator | IP: Logged

RobGrant is offline Old Post 05-10-2006 07:57 AM
Click Here to See the Profile for RobGrant Click here to Send RobGrant a Private Message Visit RobGrant's homepage! Find more posts by RobGrant Add RobGrant to your buddy list Edit/Delete Message Reply w/Quote
kichik
M.I.A.
[NSIS Dev, Mod]

Registered: Oct 2001
From: Israel

CancerFace, that page is talking about C#, not C. A few problems:

  • ZeroMemory is a macro, not a function in kernel32.dll. There's no need for it anyway. On the contrary, the first member must contain the size and not zero.
  • You should free the array returned by LsaEnumerateAccountRights using LsaFreeMemory.
  • A SID structure is not really a 1024 characters wide string, thought allocating one using AllocateAndInitializeSid doesn't seem to change a thing.
  • Your definition of UNICODE_STRING is incorrect. The first two members should be shorts, not ints. Use `&i2` instead of `i`.
RobGrant, r3 should be the name of the privilege, not a number. In my tests, the problem comes earlier where LsaEnumerateAccountRights fails and returns FILE_NOT_FOUND (check $R7 for 2). This error, according to MSDN, could mean anything.

If I keep the lookup call with the following SID generation code, I get meaningful results, 5 of them. This hints there's a problem with the user's SID, or that I don't have any privileges (?!). The following code generates the SID for the Users group.
code:
System::Call "*(&i1 0, &i4 0, &i1 5) i.r0" System::Call "advapi32::AllocateAndInitializeSid(i r0, i 2, i 32, i 545, i 0, i 0, i 0, \ i 0, i 0, i 0, *i .R1)" System::Free $0
Maybe I inherit all of my privileges from the groups that contain my user.

__________________
NSIS FAQ | NSIS Home Page | Donate $
"I hear and I forget. I see and I remember. I do and I understand." -- Confucius

Quick Link | Report this post to a moderator | IP: Logged

kichik is offline Old Post 05-10-2006 09:00 AM
Click Here to See the Profile for kichik Click here to Send kichik a Private Message Visit kichik's homepage! Find more posts by kichik Add kichik to your buddy list Edit/Delete Message Reply w/Quote
CancerFace
Senior Member

Registered: Apr 2006
From:

@kichik

quote:
Your definition of UNICODE_STRING is incorrect. The first two members should be shorts, not ints. Use `&i2` instead of `i`.
This is the real problem since I was not getting anything out on $3 when I was calling the structure from $R2.

If I create a new user and add some privilleges (logon as a service and/or anything else) then the LsaEnumerateAccountRights function returns the correct number of privileges and I am able to get the out in $3. If however I try to get the privileges for an account that has no extra privileges added, then I get the error that you mention.

CF

Quick Link | Report this post to a moderator | IP: Logged

CancerFace is offline Old Post 05-10-2006 07:20 PM
Click Here to See the Profile for CancerFace Click here to Send CancerFace a Private Message Find more posts by CancerFace Add CancerFace to your buddy list Edit/Delete Message Reply w/Quote
RobGrant
Senior Member

Registered: Sep 2004
From: Nottingham

Is it possible to pull all of that into one script?

Thanks

__________________
-rob-
Winnow Web Design
My blog
Primrose House Bed and Breakfast, Cotgrave, Nottingham

Quick Link | Report this post to a moderator | IP: Logged

RobGrant is offline Old Post 05-11-2006 02:59 PM
Click Here to See the Profile for RobGrant Click here to Send RobGrant a Private Message Visit RobGrant's homepage! Find more posts by RobGrant Add RobGrant to your buddy list Edit/Delete Message Reply w/Quote
CancerFace
Senior Member

Registered: Apr 2006
From:

I knew there was something I forgot to post here

code:
!define POLICY_LOOKUP_NAMES 0x00000800 !define strLSA_OBJECT_ATTRIBUTES '(i,i,w,i,i,i)i' !define strLSA_UNICODE_STRING '(&i2,&i2,w)i' System::Call '*${strLSA_OBJECT_ATTRIBUTES}(24,n,n,0,n,n).s' Pop $0 StrCpy $1 ${POLICY_LOOKUP_NAMES} System::Call 'advapi32::LsaOpenPolicy(w n, i r0, i r1, *i .R0) i.R8' # you can add some error checking here. If the call is succesful then $R8=0 StrCpy $2 "$UserName" ; define this somewhere StrCpy $3 ${NSIS_MAX_STRLEN} System::Call '*(&w${NSIS_MAX_STRLEN})i.R1' System::Call 'Advapi32::LookupAccountNameW(w n, w r2, i R1, *i r3, w .R8, *i r3, *i .r4) i .R8' # you can add some error checking here. If the call is succesful then $R8 <> 0 # Enumerate the rights ; R2 is the pointer to an array of LSA_UNICODE_STRING structures ; R3 is a variable that receives the number of privileges in the R2 array System::Call 'advapi32::LsaEnumerateAccountRights(i R0, i R1, *i .R2, *i .R3)i.R8' # you can add some error checking here. If the call is succesful then $R8 = 0 # Get the rights out to $4 StrCpy $9 0 loop: StrCmp $9 $R3 stop System::Call '*$R2${strLSA_UNICODE_STRING}(.r2,.r3,.r4)' DetailPrint 'Got $4' IntOp $R2 $R2 + 8 IntOp $9 $9 + 1 Goto loop stop: # Free the LSA memory System::Call 'advapi32::LsaFreeMemory(i R2) i .R8' # close the policy handle System::Call 'advapi32::LsaClose(i R0) i .R8'

Note that if your user has no extra rights then the LsaEnumerateAccountRights gives a wierd error on $R8 which you can convert to a windows error using
code:
System::Call 'advapi32::LsaNtStatusToWinError(i R8) i.R9'
and in that case $R9 is equal to 2 (check what kitchik was talking about a few posts up)
The rights will have the format that I posted before (for example SeInteractiveLogonRight)

The above works for me

CF

Quick Link | Report this post to a moderator | IP: Logged

CancerFace is offline Old Post 05-11-2006 04:51 PM
Click Here to See the Profile for CancerFace Click here to Send CancerFace a Private Message Find more posts by CancerFace Add CancerFace to your buddy list Edit/Delete Message Reply w/Quote
RobGrant
Senior Member

Registered: Sep 2004
From: Nottingham

Perfect! Thank you so much guys, that's it exactly!

__________________
-rob-
Winnow Web Design
My blog
Primrose House Bed and Breakfast, Cotgrave, Nottingham

Quick Link | Report this post to a moderator | IP: Logged

RobGrant is offline Old Post 05-18-2006 02:26 PM
Click Here to See the Profile for RobGrant Click here to Send RobGrant a Private Message Visit RobGrant's homepage! Find more posts by RobGrant Add RobGrant to your buddy list Edit/Delete Message Reply w/Quote
CancerFace
Senior Member

Registered: Apr 2006
From:

Added a WIKI page for this thread

CF

Quick Link | Report this post to a moderator | IP: Logged

CancerFace is offline Old Post 06-02-2006 10:07 PM
Click Here to See the Profile for CancerFace Click here to Send CancerFace a Private Message Find more posts by CancerFace Add CancerFace to your buddy list Edit/Delete Message Reply w/Quote
All times are GMT. The time now is 09:34 PM. Post New Thread    Post A Reply
  Last Thread   Next Thread
WINAMP.COM | Forums : Powered by vBulletin version 2.3.9 WINAMP.COM | Forums > Developer Center > NSIS Discussion > Check a user has a certain permission
Show Printable Version
 | 
Email this Page
 | 
Subscribe to this Thread

Forum Jump:
 

Forum Rules:
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is off
vB code is ON
Smilies are ON
[IMG] code is ON