cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
wimcolgate
Level 4

Security operations (LSA)

I need to set a local account right. This uses the advapi32 LsaOpenPolicy(), LookupAccountNameA(), and LsaAddAccountRights().

I cannot figure out how to accurately prototype and use these functions. I've gone through a couple of incantations, but am stymied by the very first method LsaOpenPolicy() -- the behavior is that upon making the invocation, instead of returning, the function that contains this code is exited -- if I didn't know any better, I would suspect the invocation gets an exception, trapped by IS and then cleans up. So I have very little visibility as to what is going on.

This is being done inside a Basic MSI project.

The prototypes (currently) look like this:

prototype LONG AdvApi32.LookupAccountNameA(BYREF STRING, BYREF STRING, BYREF STRING, BYREF INT, BYREF STRING, BYREF STRING, BYREF INT);
prototype LONG AdvApi32.LsaAddAccountRights(POINTER, BYREF STRING, POINTER, LONG);
prototype LONG AdvApi32.LsaClose(POINTER);
prototype LONG AdvApi32.LsaOpenPolicy(BYREF STRING, POINTER, LONG, POINTER);


The invoking code (currently) looks like this:

        nvOSResult = LsaOpenPolicy(IS_NULLSTR_PTR, &array, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &pPolicy);
if (nvOSResult == 0) then
szSIDsize = 255;
// lookup on local machine -- this *might* have to change?
nvOSResult = LookupAccountNameA(IS_NULLSTR_PTR, szUsername, szSID, szSIDsize, IS_NULLSTR_PTR, IS_NULLSTR_PTR, szUse);
if (nvOSResult != 0) then
unicode(0) = "SeServiceLogonRight";
nvOSResult = LsaAddAccountRights(pPolicy, szSID, unicode, 1);
if (nvOSResult != 0) then
_Logger(hMSI, methodName, "Failed to add service logon rights", INFORMATION, FALSE);
endif;
else
_Logger(hMSI, methodName, "Failed to lookup account name to establish service logon rights", INFORMATION, FALSE);
endif;
LsaClose(pPolicy);
else
_Logger(hMSI, methodName, "Failed to open the LSA policy to establish service logon rights", INFORMATION, FALSE);
endif;


If anyone has had any success or experience with any of the LSA functions, please show me the way!

Thanks,

Wim
Labels (1)
0 Kudos
(8) Replies
wimcolgate
Level 4

... and they gave me a link to how to get the current username:

http://kb.flexerasoftware.com/selfservice/viewContent.do?externalId=Q105753

This didn't work either (and it looks so simple -- can anyone get the above to work?). I get the same kind of result -- the custom action terminates -- no other notification, no error, no ability to catch an exception.

Does any one know how one might go about debugging this?

Regards,

Wim
0 Kudos
wimcolgate
Level 4

I was able to catch the exception on GetUsernNameA() -- 80040703 which "Failed to find DLL function". Since http://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx tells me GetUserName() (and it's ASCII variant) is in advapi32.dll --what gives? Is the linkage incorrect?

The DLL definition is:

BOOL WINAPI GetUserName(
_Out_ LPTSTR lpBuffer,
_Inout_ LPDWORD lpnSize
);


And using the prototype:

prototype BOOL Advapi32.GetUsernNameA(BYREF STRING, BYREF NUMBER);
and
prototype BOOL Advapi32.GetUsernNameA(BYREF STRING, BYREF INT);

both fail with the same exception.

Please help me stop talking to myself.

Wim
0 Kudos
wimcolgate
Level 4

So I removed the "sample" code provided in the KB article. And simply forged ahead with LsaOpenPolicy().

My prototype is:

prototype INT Advapi32.LsaOpenPolicy(BYREF WSTRING, POINTER, INT, POINTER);


And the windows definition is:

NTSTATUS LsaOpenPolicy(
_In_ PLSA_UNICODE_STRING SystemName,
_In_ PLSA_OBJECT_ATTRIBUTES ObjectAttributes,
_In_ ACCESS_MASK DesiredAccess,
_Inout_ PLSA_HANDLE PolicyHandle
);


When I execute, I get an exception 0x80020005 -- which in "type mismatch". My call is actually:

    POINTER pPolicy;
LONG array(12);
INT i;

...

i = POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES;
nvOSResult = LsaOpenPolicy(IS_NULLSTR_PTR, array, i, pPolicy);


Anyone have an idea which type is mismatching?

Thanks,

Wim
0 Kudos
Christopher_Pai
Level 16

This is a lot easier in C#:

http://blog.iswix.com/2008/09/different-year-same-problem.html


That said, it's even either if you use WiX to create a merge module that has the component for your service. (Assuming this is an MSI project) WiX has built in support for granting a service account the logon as service right. It fits into an InstallShield MSI quite nicely.
0 Kudos
wimcolgate
Level 4

... but due to release pressures, I will not be able to incorporate IsWix anytime soon.

So I am still looking to hear from the community if there is a straight InstallShield solution to the problem I am having.

Regards,

Wim
0 Kudos
wimcolgate
Level 4

To create a private C++ .dll that is a wrapper to the advapi32.dll functions I want to access -- and callable from within the MSI code (.rul code)? How would this be packaged, or spec'd our in the .ism ??
0 Kudos
Christopher_Pai
Level 16

Here's some resources:

http://helpnet.flexerasoftware.com/isxhelp19/helplibrary/MSIDLLCAs.htm

http://www.codeproject.com/Articles/1747/MSI-Custom-Action-DLL


FWIW, WiX provides some visual studio project templates that make all of this happen out of the box.


The above describes how to write a C/C++ custom action and call it directly from MSI. FWIW InstallScript follows these exact patterns ( it builds a DLL that if you examine using depends will have exported functions such as f1 f2 f3... )

You could also build the DLL using your own declaration and then prototype it from InstallScript and use the UseDLL() function to load it into memory (LoadLibrary wrapper).

Again, all possible, but there are easier ways.
0 Kudos
wimcolgate
Level 4

I put all the heavy lifting into a single C++ DLL. now there is only one function I have to call and it should be simple enough to do.

I have continue the discussion here: http://community.flexerasoftware.com/showthread.php?205797-Function-entry-point-name-for-custom-C-DLL
0 Kudos