3

I want to connect to an SMB server and browse through its files, and for a given path, to be able to retrieve a list of files and folders, with the names and permissions.

I need to support all SMB dialects, and to be able to do it from my code.

The code would like roughly as follows:

smbClient.connect(serverInfo);
info = smbClient.getShare(shareName);
for(File file : info.getFiles) {
    List<permission> permissions = file.getPermissions();
    //do something
}

I've tried a few options such as smbj, impacket, nmap, samba but none of them seem to fill my requirements above.

Is there any way to achieve the above, using Java, Python, or any linux CLI which i can call from my Java code?

zuckermanori
  • 1,675
  • 5
  • 22
  • 31
  • Depending on which properties you need to read off a shared file, and if you only need to use it as a client, pysmb might be a good choice https://github.com/miketeo/pysmb The SharedFile class should give you found file properties: http://pysmb.readthedocs.io/en/latest/api/smb_SharedFile.html – BoboDarph Jan 16 '18 at 11:02
  • Thank you @BoboDarph but pysmb only support dialects 1 and 2 and i mentioned the requirement to support all SMB dialects. – zuckermanori Jan 17 '18 at 06:51
  • The SMB3 and 3.1.1 dialects don't improve on those APIs, so in effect, SMB2 support is enough. SMB2 is a rewrite of SMB1, but SMB2.002, SMB2.1, SMB3.0 and SMB3.1.1 are all dialects (with specific improvements) over SMB2, but all use the same packets. So smbj should just work for you. Unless the server you're connecting to has explicitly disabled SMB2 or SMB2.1 as a dialect. – Hiery Nomus Mar 02 '18 at 12:45

4 Answers4

4

I guess it can help you to improve in jcifs-ng.

**// Option 1 - SMB2 and SMB3:**
Properties prop = new Properties();
prop.put( "jcifs.smb.client.enableSMB2", "true");
prop.put( "jcifs.smb.client.disableSMB1", "false");
prop.put( "jcifs.traceResources", "true" );
Configuration config = new PropertyConfiguration(prop);
CIFSContext baseContext = new BaseContext(config);
CIFSContext contextWithCred = baseContext.withCredentials(new NtlmPasswordAuthentication(baseContext, domain, fileSystemInfo.getUsername(), fileSystemInfo.getPassword()));
SmbFile share = new SmbFile(fullPath.replace('\', '/'), contextWithCred);
if (!share.exists())
{
    share.mkdirs();
}
share.close();

// Option 2 - SMB1 and CIFS:

SingletonContext context = SingletonContext.getInstance();
CIFSContext testCtx = context.withCredentials(
    new NtlmPasswordAuthentication(
        context, domain, fileSystemInfo.getUsername(), fileSystemInfo.getPassword()
    )
);
SmbFile smbFile = new SmbFile(fullPath.replace('\', '/'), testCtx);
if (!smbFile.exists())
{
    smbFile.mkdirs();
}
smbFile.close();
Leonardo Alves Machado
  • 2,747
  • 10
  • 38
  • 53
1

I don't think that there is any open source Java library that support all you need.

There is a non open source library called jNQ by "Visuality Systems"

This library support all the SMB dialects (SMB1 to SMB3.1.1)

In the link there is a code example for browsing (and you can get the security descriptor for each file in the list):

PasswordCredentials cr = new PasswordCredentials("userName", "password", "domain");
Mount mt = new Mount("IpAddress","ShareName", cr);
Directory dir = new Directory(mt, "dir1");
Directory.Entry entry;
System.out.println(DIR + " scan:");
do {
    entry = dir.next();
    if (null != entry)
        System.out.println(entry.name + " : size = " + entry.info.eof);
} while (entry != null);
Eliad Cohen
  • 378
  • 2
  • 10
1

We had the same problem, and found jcifs-ng to best answer our requirements using java (We tested it only on v1 and v2 though, but the newest version has some support for v3 as well). Your code would look like:

Configuration config = new PropertyConfiguration(new Properties());
CIFSContext context = new BaseContext(config);
context = context.withCredentials(new NtlmPasswordAuthentication(null, domain, userName, password));
String share = "smb://HOSTNAME/SHARENAME/";
try (SmbFile share = new SmbFile(url, context)) {
    for (SmbFile file : share.listFiles()) {
        ACE[] groups = file.getSecurity();
        // Do something..
    }
}

Where ACE is an Access Control Entry, which is an element that controls or monitors an access to an object (is short, a permission).

Notice that the newest version might not be on Maven or Gradle yet, so you'll have to clone the repo and build it by yourself.

Norman
  • 11
  • 1
0

If you are running Windows and the user running the program has access to the share, you could do it just by using java.nio. Java.nio allows you to access SMB shares.

Path path = Paths.get(<SharedFile>);
AclFileAttributeView aclAttribute = Files.getFileAttributeView(path, AclFileAttributeView.class);

Then you can use aclAttribute.getAcls(); to get the users and their permissions.

lechbrush
  • 66
  • 4
  • Thank you @lech_uk. The user running the program does not have access to this file, but I do have in hand user credentials that have access to this file. As far as I understand, there is no way to programatically login with a given user, and also, according to the JavaDoc AclFileAttributeView supports only NFS and not SMB. – zuckermanori Jan 17 '18 at 06:57