wntAccessGet error

Started by etippelt, March 03, 2017, 10:34:32 AM

Previous topic - Next topic

etippelt

Basically, I am trying to write a utility that will scan a directory tree and list the permissions on the files and folders.
It's working, apart from a problem with wntAccessGet which on certain "files" reports WIL Extender Error 542: Invalid User/Group Name.

Having had a look in the displayed permissions of the sample file concerned, (C:\ProgramData\regid.1991-06.com.microsoft\regid.1991-06.com.microsoft Microsoft Office Professional Plus 2013.swidtag), there are two "groups" with a different symbol which are causing the error. The groups in this case are called ALL APPLICATION PACKAGES and ALL RESTRICTED APPLICATION PACKAGES.
Instead of the "Two person" symbol, the symbol looks like a couple of sheets of paper with images on them.  (see attached image)
Any ideas why these groups are causing an error with wntAccessGet when they are happily retrieved by the wntAccessList command.

Thanks
Ed
Using Winbatch since 1995. Excellent tool, awesome support always.

td

The two groups are special system groups used to grant access to objects by "Windows Store" apps or "UWP" apps or whatever MSFT is calling them this week. 

Assuming you are running with sufficient privileges (most users can read privileges),  can't say why wntAccessGet is not recognizing those groups.  The function happily returns permissions for those groups on my Windows 10 workstation.  You might want to check your function parameters to make sure they are correct.  You could try using the two group's SIDs instead of their names but that was not necessary on my system.     
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

The simple test used to check the access function:

Code (winbatch) Select
AddExtender("wwwnt34i.dll",0,"wwwnt64i.dll")         ; Installs a WIL extender dll.
strPrivs1 = wntAccessGet("", 'C:\ProgramData\regid.1991-06.com.microsoft', 'ALL APPLICATION PACKAGES', 300)
strPrivs2 = wntAccessGet("", 'C:\ProgramData\regid.1991-06.com.microsoft', 'ALL RESTRICTED APPLICATION PACKAGES', 300)
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

etippelt

Hi td,
Thank you for the script suggestion, but in your example, you are quoting a folder location, and not a file within that folder.
So for example, in my script, I am running wntAccessGet on the following resource:  C:\ProgramData\regid.1991-06.com.microsoft\regid.1991-06.com.microsoft Microsoft Office Professional Plus 2013.swidtag
It is that request that is causing the error. I am basically using the file extender to itemise the list of files in a subdirectory tree and then passing each file to the wntAcccessGet command. The code extract looks like this:

fh=FileOpen(outfile,"WRITE") 
Edcount=0    ;pointer to keep track of search hits
If silent==0 then BoxOpen("","")

;Start of search loop
For i=1 to param0
Extvar=param%i%

   If silent==0 then BoxTitle("Searching from %Drivep%")
   If StrSub(Drivep,StrLen(Drivep),1)!= "\" Then Drivep=StrCat(Drivep,"\")
   
   handle=fafOpen(Drivep,Extvar,144)

:start
        Edfile=fafFind(handle)
        if Edfile=="" then goto finish 
        Edcount=Edcount+1
        pos=StrIndex(Edfile,"\",0,@backscan)+1
        filename=StrSub(Edfile,pos,-1)
        FileWrite(fh,Edfile)

        aList = wntAccesslist("",EdFile,300,3)
        ;Get the list of items
        aListcount = ItemCount(aList, @TAB)
        If aListcount > 0
          For j=1 to aListcount
          group=ItemExtract(j,aList,@TAB)
          ;Message("",Group)
           If group == "APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES" || group == "APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES"
            records = "Not Read"
           Else
            records = wntAccessGet("",EdFile,group,300,0)
           EndIf
          ;Message("",records)
          group = strCat(group,@TAB,records)
          FileWrite(fh,group)
          Next
        Endif
        FileWrite(fh,@CRLF)

        if silent==0 then BoxText(EdFile)
        goto start
:finish
   fafClose(handle)

Next

Fileclose(fh)


You can see where I have added some code to detect the problem groups and not try to extract the permissions, but before I did this, the code bombed every time.

So let me know what I might have overlooked!

Cheers
Ed
Using Winbatch since 1995. Excellent tool, awesome support always.

ChuckC

Take a look at your wwwbatch.ini file, as the various wnt*() extender-based functions are pretty good at recording diagnostic information there when an underlying Win32 API function call fails.

If I'm understanding things correctly, wntAccessList() is able to identify these accounts as security principals to which permissions have been assigned on the specified files, and the account names are returned in a delimited list.  However, calls to wntAccessGet() for these account names results in an error which means that the account name couldn't be translated into a SID value.   If that's the case, then the underlying Win32 API functions used to convert between SID and account names are most likely failing to "round trip", with LookupAccountSidW() being able to take the SID value from an ACE in the DACL and convert it to "APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES", but then, later, a call to LookupAccountNameW() fails convert that fully-qualified account name into a SID value.

IIRC, there's code buried down inside the Win32 Network Extender that deals with this type of issue since there are certain well-known domain names that get returned when converting a SID to an account name that cannot be present when attempting to convert an account name back to a SID value.  If the problem is what I think it is, though, then "APPLICATION PACKAGE AUTHORITY" is also another one of those types of well-known domain names.

To test that theory, try calling wntAccessGet() for those accounts, but trim off the pseudo-domain prefix up to and including the '\' character, such that you only try to get the assigned permissions for "ALL RESTRICTED APPLICATION PACKAGES" and "ALL APPLICATION PACKAGES".  If that is successful, then you'll have to test for the presence of the well-known domain prefix "APPLICATION PACKAGE AUTHORITY\" and remove it from the values returned by wntAccessList() before making calls to wntAccessGet().

If this proves to be the case, then, long term, the Win32 NetWork extender may need to have some slight modifications made to it w/respect to the internal methods it uses for performing translations between SID values and account names so that the problem can be silently dealt with and prevented from happening regardless of whether or not you pass in the account name with or without that particular well-known domain prefix on it.

td

In testing on my Windows 10 workstation the distinction between a directory and file has no merit.   The above simple example works equally well with either file or directory as would be expected when using only the group name. 

The problem is that you are using the fully qualified group name instead of simply using the group name as is the case in the simple example.  There is a well reported (although not acknowledged by MSFT) bug in the Win32 security API function used to lookup fully qualified names containing the APPLICATION PACKAGE AUTHORITY domain even though APPLICATION PACKAGE AUTHORITY has a well known SID.

So you have several choices; you can strip out the APPLICATION PACKAGE AUTHORITY domain from the group name before calling wntAccessGet or call wntAccessList with the flags parameter set to 0 so that the returned names do not have APPLICATION PACKAGE AUTHORITY domain prepended to them.   You may also want to consider using SIDs instead of names to identify your groups but I have not tested this to confirm that it works.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

ChuckC

The various wntAccess*() and wntSecurity*() functions that work with ACEs in the DACL/SACL will take SID values in addition to the account name values when identifying a security principal for which an ACE is to be retrieved, removed or otherwise modified.  If the well-known SID values for these particular groups are specified, they'll work just fine.


td

Yes, it does work.  I prefer not to assert that something works unless I have tried it (it can otherwise be embarrassing).  In this case I took the time to test it and it works.  The two SIDs of interest are S-1-15-2-1 and S-1-15-2-2
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

As expected, reverse lookup works as well:

Code (winbatch) Select
AddExtender("wwwnt34i.dll",0,"wwwnt64i.dll")

strAllPacks = wntAcctInfo( "", 'S-1-15-2-1', 2, 1)
strAllRestd = wntAcctInfo( "", 'S-1-15-2-2', 2, 1)
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

ChuckC

I felt comfortable making the assertion since the provenance of the code behind that functionality is well known to me :P

td

"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

etippelt

Quote from: ChuckC on March 06, 2017, 06:15:03 AM
Take a look at your wwwbatch.ini file, as the various wnt*() extender-based functions are pretty good at recording diagnostic information there when an underlying Win32 API function call fails.

If I'm understanding things correctly, wntAccessList() is able to identify these accounts as security principals to which permissions have been assigned on the specified files, and the account names are returned in a delimited list.  However, calls to wntAccessGet() for these account names results in an error which means that the account name couldn't be translated into a SID value.   If that's the case, then the underlying Win32 API functions used to convert between SID and account names are most likely failing to "round trip", with LookupAccountSidW() being able to take the SID value from an ACE in the DACL and convert it to "APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES", but then, later, a call to LookupAccountNameW() fails convert that fully-qualified account name into a SID value.

IIRC, there's code buried down inside the Win32 Network Extender that deals with this type of issue since there are certain well-known domain names that get returned when converting a SID to an account name that cannot be present when attempting to convert an account name back to a SID value.  If the problem is what I think it is, though, then "APPLICATION PACKAGE AUTHORITY" is also another one of those types of well-known domain names.

To test that theory, try calling wntAccessGet() for those accounts, but trim off the pseudo-domain prefix up to and including the '\' character, such that you only try to get the assigned permissions for "ALL RESTRICTED APPLICATION PACKAGES" and "ALL APPLICATION PACKAGES".  If that is successful, then you'll have to test for the presence of the well-known domain prefix "APPLICATION PACKAGE AUTHORITY\" and remove it from the values returned by wntAccessList() before making calls to wntAccessGet().

If this proves to be the case, then, long term, the Win32 NetWork extender may need to have some slight modifications made to it w/respect to the internal methods it uses for performing translations between SID values and account names so that the problem can be silently dealt with and prevented from happening regardless of whether or not you pass in the account name with or without that particular well-known domain prefix on it.

Hi Chuck,
I checked the wwwbatch.ini and there was indeed a message about not being able to resolve a SID, so my next test will be to detect these particular groups and substitute the SID for them.  Truncating the names did not work as the call then barfed.  The one problem with this logfile is that there is no date or timestamp showing when an operating was logged, and clearly some entries in there are from a different project entirely. If there is still time in the development process, that's one limitation I would like to see fixed before retirement!
Cheers
Ed
Using Winbatch since 1995. Excellent tool, awesome support always.

td

Quote from: etippelt on March 07, 2017, 02:46:13 AM

Hi Chuck,
I checked the wwwbatch.ini and there was indeed a message about not being able to resolve a SID, so my next test will be to detect these particular groups and substitute the SID for them.  Truncating the names did not work as the call then barfed.  The one problem with this logfile is that there is no date or timestamp showing when an operating was logged, and clearly some entries in there are from a different project entirely. If there is still time in the development process, that's one limitation I would like to see fixed before retirement!
Cheers
Ed

Yes, we have a good idea what you will see in the wwwbatch.ini file.   It will be something like this

LastError=0 ({Unable to resolve a SID} : DoFormatAcctNameOrSid())

Which as mentioned in several previous posts this is the result of a bug in the Win32 API security function (LookupAccountSidA - not 'W' as it is called from a DBCS dll) that among other things translates text based domain\user or group style names to binary SIDs.   Also as mentioned previously, when you removed the domain name and backslash (\) from the full domain\group the function does work in our testing and as reported by other developers that have encountered this problem.  If you are not getting a successful result, you may want to consider performing some debugging to confirm that you are passing what you think you are passing to the function.  In any case, since the two groups have well-known-SID, you can use the SIDs as mentioned above or use the result of wntAccessList with the flag value set to 4.   The latter approach likely being the best depending on your requirements.  Just make sure you provided the correct parameters to the call to wntAccessGet for handling SIDs.

With regard to a time stamp of some kind in the wwwbatch.ini file, that is not likely to happen given the remaining priorities.  Instead you may want to consider simply deleting the contents of the file before you make a test run.  Keep in mind that all extenders and the WIL dll itself use this file to preserve additional error information.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

ChuckC

Another caveat worth mentioning:

As newer versions of Windows are released that have support for these new well-known accounts and their associated SID values, remember that older versions of Windows are not able to perform these conversions between account names and SID values for the new well-known accounts.  In practical terms, it means that the "server-name" parameter on the calls to the various wntAccess*()/wntAudit*() functions needs to refer to a Windows Server that's running a new enough version of Windows to perform the name/SID conversions.  When you are dealing with local paths [e.g. drive letters], the "server-name" parameter is left empty so that the local system is used.  However, if the local computer where the code is executing is running an older version of Windows that doesn't support the newer well-known account names & SID values, then you'll get name/SID conversion errors.

Given that the OP's posted code shows using wntAccessList() to obtain the account names associated with the ACEs on a file, this particular issue is not likely to be the root-cause of the problem, but it's still worthy of being aware of for future reference.

td

Given the OP's posted script, I did not broach the subject of supporting versions of Windows and remote access but good points none the less.  The OP may actually be doing something other than what is indicated by the posted script.   It wouldn't be the first time.

We do test the extender on newer version of Windows and we tested this particular issue on Windows 8, Windows 8.1, Windows 2012R2 and several installations of Windows 10 (latest release build.)    Pre-Windows 10 versions of Windows only support the 'S-1-15-2-1' well-known-SID.  Windows 10 supports both the 'S-1-15-2-1' and 'S-1-15-2-2'  SIDs.  The same applies to the 'ALL APPLICATION PACKAGES' and 'ALL RESTRICTED APPLICATION PACKAGES' named versions of those groups of course.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

etippelt

First of all, many thanks for the help and code suggestions. I managed to get the program working by screening out the strings and using SID substitution for them.
My target platforms are Win 7 and Win 10, so no issues are likely to arise with older operating systems.
I work in the app packaging and deployment field, and there are occasionally apps that are setting permissions as part of an installation, and no existing capture tools that I am aware of, provide the capability of recording permission changes to files and folders. So I now have a tool where I can perform a permissions scan of a folder tree, do the installation, then run the scan again, and compare results.
Thanks again Guys!
Using Winbatch since 1995. Excellent tool, awesome support always.