[jcifs] Re: Resolve SIDs in ACE

Jake Goulding goulding at vivisimo.com
Tue May 30 19:22:42 GMT 2006

This feature is something that would be extremely valuable for a project 
I am working on. I set up the J2EE environment and wrangled with ant to 
be able to compile JCIFS with the ACL resolving patch. I believe that I 
have everything compiling fine, and my class path is set correctly, but 
I am getting this error when actually trying to use the functionality:

$ java -classpath jcifs.jar:jarapac.jar:. SMB  smb://pdc/office/chris.xml
Using path: smb://pdc/office/chris.xml
jcifs.smb.SmbException: Unable to resolve SIDs
rpc.ProviderException: Unable to find suitable provider for 
        at rpc.Stub.attach(Stub.java:105)
        at rpc.Stub.call(Stub.java:110)
        at jcifs.rpc.LsaRPC.openPolicy(LsaRPC.java:62)
        at jcifs.rpc.LsaRPC.lookupSids(LsaRPC.java:94)
        at jcifs.smb.SmbFile.getSecurity(SmbFile.java:2528)
        at SMB.get_acl_string(SMB.java:119)
        at SMB.main(SMB.java:152)

        at jcifs.smb.SmbFile.getSecurity(SmbFile.java:2530)
        at SMB.get_acl_string(SMB.java:119)
        at SMB.main(SMB.java:152)

Can anyone shed some light on this for me?

I also agree with someone else that it would be nice to see this 
included by default, but I understand the need to do it right.

Thanks for the hard work!


>  No. This is something that needs a little work.
>  First, there really needs to be some code to find the right host to
>  query for resolving SIDs. Querying the server of the target object as
>  shown in the code below is not correct (although it might work).
>  There needs to be a lookup that indicates the correct host for
>  resolving a specific SID. As I'm sure you know by now a SID is
>  composed of a domain part and and a relative identifier:
>  SID: S-1-5-21-12345-23456-34567-1122 Domain SID:
>  S-1-5-21-12345-23456-34567 RID: 1122
>  So you need to lookup the domain/machine name that maps to the domain
>  SID S-1-5-21-12345-23456-34567. Then you do a NetBIOS lookup (or
>  preferrably an SRV DNS query) to determine the IP (possibly via DNS
>  hostname) of a specific server for the target name. Then you do an
>  LSA bind with that server and perform the LsarLookupSids call to
>  resolve one or more sids that begin with the target domain SID. I'm
>  not certain that all of these steps are necessary. It could be that
>  any local domain controller will recursively query other domain
>  controllers on your behalf but that would require some
>  experimentation. If I were doing this I would most certainly obtain
>  packet captures of a Windows client peforming the desired operations
>  (e.g. write a small Win32 program that models your application). Then
>  I could know definitively how the Java side should behave.
>  Second, there needs to be a SID cache. Without a SID cache the domain
>  controller could become overloaded with requests to resolve SIDs
>  (depending on the application of course). SIDs NEVER change so they
>  can be heavily cached. So the interface should be adjusted a little.
>  Specifically, add hashCode() and equals() methods to the SID class.
>  Add a 'state' member to the SID class with possible states ST_GROUND,
>  ST_RESOLVING, ST_FAILED, and ST_RESOLVED. Also add a 'name' member
>  to hold the result of the name corresponding to the sid (e.g.
>  'FOONET\Domain Admins', 'FOONET\tbley', 'BARNET\Backup Operator',
>  etc). Now when a SID needs to be resolved you query a hash map (the
>  SID cache). If the SID is found, check the state - if the state is
>  ST_RESOLVED, return success - if the state is ST_FAILED, return
>  failure - if the state is ST_RESOLVING, call wait() on the map. If
>  the SID is NOT found in the map, set the state of the callers SID to
>  ST_RESOLVING, insert it into the map, and proceed to resolve it using
>  the said technique of looking up the correct domain, doing the
>  LsarLookupSids call and so on. When resolved, set the state to
>  ST_RESOLVED or ST_FAILED and notify() on the map. This is all
>  off-the-top-of-my-head of course.
>  In general, the patch is not optimal for resolving arbitrary SIDs
>  because it doesn't provide any facility to locate the correct LSA
>  database. However, if you're certain that the SIDs will all be in the
>  same domain (usually are) or after some experimentation you find
>  that a target machine will recursively query other domains to some
>  degree then it may be possible to simply use "new
>  LsaRPC(<domainController>)" where domainController is the IP of a
>  local domain controller (or in your case a workstation IP). For
>  example, in the case of the NTLM HTTP Filter this simplified
>  technique might be suffecient (although a cache is STRONGLY
>  recommended for the Filter).
>  Anyway I suppose I've only dug a deeper hole than the one you're in.
>  The short answer is to pass the SmbFile.auth member to the LsaRPC
>  constructor or lookupSids() call so that they can in turn pass the
>  NPA to the SmbNamePipe constructor (wherever that is - I don't
>  recall).
>  You should realize that querying individual hosts for SID names is
>  unusual. In a MS client's natural habitat it would query the domain
>  controller(s) directly (and probably cache the results).
>  Mike

Jake Goulding
Software Engineer
Vivísimo, Inc.

"One of the main causes of the fall of the Roman Empire was that,
lacking zero, they had no way to indicate successful termination
of their C programs."

More information about the jcifs mailing list