hierynomus / smbj

Server Message Block (SMB2, SMB3) implementation in Java
Other
707 stars 180 forks source link

DFS Resolve Failure #322

Open obit91 opened 6 years ago

obit91 commented 6 years ago

Hello.

I'm attempting to access a file on a share which is actually a link to a file on a different server. It seems that the DFS Resolver resolves the whole file path to a partial path to the second share, thus failing to access the file.

Here is an example (edited server/share/user names for security):

[Test_test smb] INFO com.hierynomus.smbj.share.DFSDiskShare - DFS Share DFSDiskShare[\\serverName.suffix\shareName] does not cover folder1/folder2/fileExample.pdf, resolve through DFS
[Test_test smb] INFO com.hierynomus.smbj.share.DFSPathResolver - Starting DFS resolution for \\serverName.suffix\shareName\folder1/folder2/fileExample.pdf
[Test_test smb] INFO com.hierynomus.smbj.session.Session - Connecting to \\serverName\IPC$ on session 5473562397126750605
[Test_test smb] INFO com.hierynomus.smbj.share.DFSDiskShare - DFS resolved \\serverName.suffix\shareName\folder1/folder2/fileExample.pdf -> \\secondServerName.suffix\secondShareName
[Test_test smb] INFO com.hierynomus.smbj.connection.Connection - Successfully authenticated myUsername on secondServerName.suffix, session is 1155173304421441560
[Test_test smb] INFO com.hierynomus.smbj.session.Session - Connecting to secondServerName.suffix\secondShareName on session 1155173304421441560
com.hierynomus.mssmb2.SMBApiException: STATUS_FILE_IS_A_DIRECTORY(3221225658/3221225658): Create failed for null

Thanks for your time.

jborza commented 6 years ago

Which DiskShare method are you using?

obit91 commented 6 years ago

Setting up the session:

SmbConfig cfg = SmbConfig
        .builder()
        .withMultiProtocolNegotiate(true)
        .withDfsEnabled(true)
        .withNegotiatedBufferSize()
        .withSoTimeout(DEFAULT_SO_TIMEOUT, DEFAULT_SO_TIMEOUT_UNIT)
        .build();
    SMBClient client = new SMBClient(cfg);
    try {
        connection = client.connect(hostname);
        AuthenticationContext ac = new AuthenticationContext(user, pass.toCharArray(), domain);
        session = connection.authenticate(ac);
        authenticated = true;

Accessing files:

public static DiskEntry readFile(String pathOnShare, DiskShare share) {
    if (shareToCheck.folderExists(pathOnShare)) {
        return parseDir(pathOnShare, share);
    } else {
        return parseFile(pathToCheck, shareToCheck);
    }

Which uses (in this example):

private static DiskEntry parseFile(String pathOnShare, DiskShare share) {
    String innerPath = Samba.removeSMBPathPrefix(pathOnShare, share);
    Set<AccessMask> accessMasks = new HashSet<>(EnumSet.of(AccessMask.FILE_READ_DATA,
        AccessMask.FILE_READ_ATTRIBUTES, AccessMask.FILE_READ_EA, AccessMask.SYNCHRONIZE));
    Set<SMB2ShareAccess> shareAccess = new HashSet<>(EnumSet.of(SMB2ShareAccess.FILE_SHARE_READ,
        SMB2ShareAccess.FILE_SHARE_WRITE, SMB2ShareAccess.FILE_SHARE_DELETE));
    Set<SMB2CreateOptions> createOptions = new HashSet<>(EnumSet.of(SMB2CreateOptions.FILE_NON_DIRECTORY_FILE));
    return share.openFile(innerPath, accessMasks, null, shareAccess, SMB2CreateDisposition.FILE_OPEN,
        createOptions);
    }

You can ignore innerPath, it just drops prefix (smb:// etc) in case it exists, which is irrelevant in this bug.