hierynomus / smbj

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

STATUS_ACCESS_DENIED with SMB3 and DFS share #652

Closed jansohn closed 1 year ago

jansohn commented 3 years ago

We're getting a com.hierynomus.mssmb2.SMBApiException: STATUS_ACCESS_DENIED (0xc0000022) error when trying to create a directory on a DFS share. I know that this indicates a permission problem but connecting via smbclient and performing a mkdir command works without any issues so I don't think that the user's permissions are the problem: smbclient -m SMB3 //emea.my-company.com/frd -D public/transfer -U user -W emea

Forcing the dialect to SMB2Dialect.SMB_2_1 also "fixes" the problem.

Code:

Configuration config = new Configuration();
config.readPropertiesFromFile();

AuthenticationContext authContext = new AuthenticationContext(config.getSambaConfig().getUsername(),
        config.getSambaConfig().getPassword().toCharArray(),
        config.getSambaConfig().getDomain());

SmbConfig clientConfig = SmbConfig.builder()
        .withDfsEnabled(true)
        .withSecurityProvider(new BCSecurityProvider())
        // .withDialects(SMB2Dialect.SMB_2_1)
        .withMultiProtocolNegotiate(true)
        .withSigningRequired(true)
        .build();

SmbPath remoteDir = SmbPath.parse("\\\\emea.my-company.com\\frd\\public\\transfer\\dfsTest");

// Connect to share
try (SMBClient client = new SMBClient(clientConfig);
        Connection connection = client.connect(remoteDir.getHostname());
        Session session = connection.authenticate(authContext);
        DiskShare diskShare = (DiskShare) session.connectShare(remoteDir.getShareName()))
{
    log.info("Connected to {} with Samba protocol {}", remoteDir.getHostname(), connection.getNegotiatedProtocol().getDialect());
    diskShare.mkdir(remoteDir.getPath());
}

Log:

INFO  [main] com.company.api.samba.DfsTest: -------------------- createDirectory ---------------------
DEBUG [main] com.hierynomus.protocol.commons.socket.ProxySocketFactory: Connecting to emea.my-company.com/10.130.1.190:445
INFO  [main] com.hierynomus.smbj.paths.DFSPathResolver: Attempting to resolve \\emea.my-company.com\frd through DFS
INFO  [main] com.hierynomus.smbj.paths.DFSPathResolver: Starting DFS resolution for \\emea.my-company.com\frd
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[1]: ResolveState{path=DFSPath{[emea.my-company.com, frd]}, resolvedDomainEntry=false, isDFSPath=false, hostName='null'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[2]: ResolveState{path=DFSPath{[emea.my-company.com, frd]}, resolvedDomainEntry=false, isDFSPath=false, hostName='null'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[5]: ResolveState{path=DFSPath{[emea.my-company.com, frd]}, resolvedDomainEntry=false, isDFSPath=false, hostName='null'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[6]: ResolveState{path=DFSPath{[emea.my-company.com, frd]}, resolvedDomainEntry=false, isDFSPath=false, hostName='emea.my-company.com'}
INFO  [main] com.hierynomus.smbj.paths.DFSPathResolver: Got DFS Referral result: \emea.my-company.com\frd->\SERVER03088.EMEA.my-company.com\FRD(ROOT), [TargetSetEntry[\SERVER03088.EMEA.my-company.com\FRD,targetSetBoundary=false], TargetSetEntry[\SERVER03089.EMEA.my-company.COM\FRD,targetSetBoundary=false], TargetSetEntry[\SERVER03090.EMEA.my-company.COM\FRD,targetSetBoundary=false]]
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[7]: ResolveState{path=DFSPath{[emea.my-company.com, frd]}, resolvedDomainEntry=false, isDFSPath=false, hostName='emea.my-company.com'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[3]: ResolveState{path=DFSPath{[emea.my-company.com, frd]}, resolvedDomainEntry=false, isDFSPath=false, hostName='emea.my-company.com'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[8]: ResolveState{path=DFSPath{[SERVER03088.EMEA.my-company.com, FRD]}, resolvedDomainEntry=false, isDFSPath=true, hostName='emea.my-company.com'}
DEBUG [main] com.hierynomus.protocol.commons.socket.ProxySocketFactory: Connecting to SERVER03088.EMEA.my-company.com/10.189.85.21:445
INFO  [main] com.company.api.samba.DfsTest: Connected to emea.my-company.com with Samba protocol SMB_3_0_2
INFO  [main] com.hierynomus.smbj.paths.DFSPathResolver: Starting DFS resolution for \\SERVER03088.EMEA.my-company.com\FRD\public\transfer\dfsTest
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[1]: ResolveState{path=DFSPath{[SERVER03088.EMEA.my-company.com, FRD, public, transfer, dfsTest]}, resolvedDomainEntry=false, isDFSPath=false, hostName='null'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[2]: ResolveState{path=DFSPath{[SERVER03088.EMEA.my-company.com, FRD, public, transfer, dfsTest]}, resolvedDomainEntry=false, isDFSPath=false, hostName='null'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[5]: ResolveState{path=DFSPath{[SERVER03088.EMEA.my-company.com, FRD, public, transfer, dfsTest]}, resolvedDomainEntry=false, isDFSPath=false, hostName='null'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[6]: ResolveState{path=DFSPath{[SERVER03088.EMEA.my-company.com, FRD, public, transfer, dfsTest]}, resolvedDomainEntry=false, isDFSPath=false, hostName='SERVER03088.EMEA.my-company.com'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[12]: ResolveState{path=DFSPath{[SERVER03088.EMEA.my-company.com, FRD, public, transfer, dfsTest]}, resolvedDomainEntry=false, isDFSPath=false, hostName='SERVER03088.EMEA.my-company.com'}
INFO  [main] com.company.api.samba.DfsTest: Test failed for createDirectory with reason STATUS_ACCESS_DENIED (0xc0000022): Create failed for \\SERVER03088.EMEA.my-company.com\FRD\public\transfer\dfsTest

Stacktrace:

com.hierynomus.mssmb2.SMBApiException: STATUS_ACCESS_DENIED (0xc0000022): Create failed for \\SERVER03088.EMEA.zf-world.com\FRD\public\transfer\dfsTest
    at com.hierynomus.smbj.share.Share.receive(Share.java:397)
    at com.hierynomus.smbj.share.Share.sendReceive(Share.java:377)
    at com.hierynomus.smbj.share.Share.createFile(Share.java:159)
    at com.hierynomus.smbj.share.DiskShare.createFileAndResolve(DiskShare.java:75)
    at com.hierynomus.smbj.share.DiskShare.access$100(DiskShare.java:55)
    at com.hierynomus.smbj.share.DiskShare$2.apply(DiskShare.java:109)
    at com.hierynomus.smbj.share.DiskShare$2.apply(DiskShare.java:105)
    at com.hierynomus.smbj.paths.DFSPathResolver.step12(DFSPathResolver.java:380)
    at com.hierynomus.smbj.paths.DFSPathResolver.step6(DFSPathResolver.java:273)
    at com.hierynomus.smbj.paths.DFSPathResolver.step5(DFSPathResolver.java:222)
    at com.hierynomus.smbj.paths.DFSPathResolver.step2(DFSPathResolver.java:141)
    at com.hierynomus.smbj.paths.DFSPathResolver.step1(DFSPathResolver.java:124)
    at com.hierynomus.smbj.paths.DFSPathResolver.start(DFSPathResolver.java:112)
    at com.hierynomus.smbj.paths.DFSPathResolver.resolve(DFSPathResolver.java:100)
    at com.hierynomus.smbj.share.DiskShare.resolveAndCreateFile(DiskShare.java:105)
    at com.hierynomus.smbj.share.DiskShare.open(DiskShare.java:65)
    at com.hierynomus.smbj.share.DiskShare.openDirectory(DiskShare.java:151)
    at com.hierynomus.smbj.share.DiskShare.mkdir(DiskShare.java:274)
    at com.company.api.samba.DfsTest.createDirectory(DfsTest.java:57)

Log (SMB_2_1):

INFO  [main] com.comapny.api.samba.DfsTest: -------------------- createDirectory ---------------------
DEBUG [main] com.hierynomus.protocol.commons.socket.ProxySocketFactory: Connecting to emea.my-company.com/10.130.1.190:445
INFO  [main] com.hierynomus.smbj.paths.DFSPathResolver: Attempting to resolve \\emea.my-company.com\frd through DFS
INFO  [main] com.hierynomus.smbj.paths.DFSPathResolver: Starting DFS resolution for \\emea.my-company.com\frd
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[1]: ResolveState{path=DFSPath{[emea.my-company.com, frd]}, resolvedDomainEntry=false, isDFSPath=false, hostName='null'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[2]: ResolveState{path=DFSPath{[emea.my-company.com, frd]}, resolvedDomainEntry=false, isDFSPath=false, hostName='null'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[5]: ResolveState{path=DFSPath{[emea.my-company.com, frd]}, resolvedDomainEntry=false, isDFSPath=false, hostName='null'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[6]: ResolveState{path=DFSPath{[emea.my-company.com, frd]}, resolvedDomainEntry=false, isDFSPath=false, hostName='emea.my-company.com'}
INFO  [main] com.hierynomus.smbj.paths.DFSPathResolver: Got DFS Referral result: \emea.my-company.com\frd->\SERVER03089.EMEA.my-company.COM\FRD(ROOT), [TargetSetEntry[\SERVER03089.EMEA.my-company.COM\FRD,targetSetBoundary=false], TargetSetEntry[\SERVER03090.EMEA.my-company.COM\FRD,targetSetBoundary=false], TargetSetEntry[\SERVER03088.EMEA.my-company.com\FRD,targetSetBoundary=false]]
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[7]: ResolveState{path=DFSPath{[emea.my-company.com, frd]}, resolvedDomainEntry=false, isDFSPath=false, hostName='emea.my-company.com'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[3]: ResolveState{path=DFSPath{[emea.my-company.com, frd]}, resolvedDomainEntry=false, isDFSPath=false, hostName='emea.my-company.com'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[8]: ResolveState{path=DFSPath{[SERVER03089.EMEA.my-company.COM, FRD]}, resolvedDomainEntry=false, isDFSPath=true, hostName='emea.my-company.com'}
DEBUG [main] com.hierynomus.protocol.commons.socket.ProxySocketFactory: Connecting to SERVER03089.EMEA.my-company.COM/10.189.85.22:445
INFO  [main] com.comapny.api.samba.DfsTest: Connected to emea.my-company.com with Samba protocol SMB_2_1
INFO  [main] com.hierynomus.smbj.paths.DFSPathResolver: Starting DFS resolution for \\SERVER03089.EMEA.my-company.COM\FRD\public\transfer\dfsTest
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[1]: ResolveState{path=DFSPath{[SERVER03089.EMEA.my-company.COM, FRD, public, transfer, dfsTest]}, resolvedDomainEntry=false, isDFSPath=false, hostName='null'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[2]: ResolveState{path=DFSPath{[SERVER03089.EMEA.my-company.COM, FRD, public, transfer, dfsTest]}, resolvedDomainEntry=false, isDFSPath=false, hostName='null'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[5]: ResolveState{path=DFSPath{[SERVER03089.EMEA.my-company.COM, FRD, public, transfer, dfsTest]}, resolvedDomainEntry=false, isDFSPath=false, hostName='null'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[6]: ResolveState{path=DFSPath{[SERVER03089.EMEA.my-company.COM, FRD, public, transfer, dfsTest]}, resolvedDomainEntry=false, isDFSPath=false, hostName='SERVER03089.EMEA.my-company.COM'}
INFO  [main] com.hierynomus.smbj.paths.DFSPathResolver: Got DFS Referral result: \SERVER03089.EMEA.my-company.COM\FRD\public\transfer->\frda90133.emea.my-company.com\c90133_71$(LINK), [TargetSetEntry[\frda90133.emea.my-company.com\c90133_71$,targetSetBoundary=false]]
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[7]: ResolveState{path=DFSPath{[SERVER03089.EMEA.my-company.COM, FRD, public, transfer, dfsTest]}, resolvedDomainEntry=false, isDFSPath=false, hostName='SERVER03089.EMEA.my-company.COM'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[4]: ResolveState{path=DFSPath{[SERVER03089.EMEA.my-company.COM, FRD, public, transfer, dfsTest]}, resolvedDomainEntry=false, isDFSPath=false, hostName='SERVER03089.EMEA.my-company.COM'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[3]: ResolveState{path=DFSPath{[SERVER03089.EMEA.my-company.COM, FRD, public, transfer, dfsTest]}, resolvedDomainEntry=false, isDFSPath=false, hostName='SERVER03089.EMEA.my-company.COM'}
TRACE [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS[8]: ResolveState{path=DFSPath{[frda90133.emea.my-company.com, c90133_71$, dfsTest]}, resolvedDomainEntry=false, isDFSPath=true, hostName='SERVER03089.EMEA.my-company.COM'}
DEBUG [main] com.hierynomus.protocol.commons.socket.ProxySocketFactory: Connecting to frda90133.emea.my-company.com/10.189.70.183:445
INFO  [main] com.hierynomus.smbj.paths.DFSPathResolver: DFS resolved \\SERVER03089.EMEA.my-company.COM\FRD\public\transfer\dfsTest -> com.hierynomus.smbj.share.DiskShare$SMB2CreateResponseContext@266374ef
INFO  [main] com.comapny.api.samba.DfsTest: Test succeeded for createDirectory
jansohn commented 3 years ago

sounds similar to #645 but we do not specify any access masks ourselves but rather just use the provided diskShare.mkdir(...)...

rokkakasu commented 3 years ago

Hi @jansohn ,

if you are not using NAS share then please try with Version 3_1_1 it works perfectly fine. and use SMBJ Dependency version 0.11.1 or take from master.

Thanks, R Ramarajan.

jansohn commented 3 years ago

We're using the latest version 0.11.1 and our DFS share seems to be stuck with 3_0_2 at the moment (I guess it is still a Windows Server 2012). I do not manage the DFS shares, though...

rokkakasu commented 3 years ago

Hi Jansohn Change // .withDialects(SMB2Dialect.SMB_2_1) to // .withDialects(SMB2Dialect.SMB_3_1_1) and try it will work.

thanks, R Ramarajan.

hierynomus commented 3 years ago

@vrr6 That is commented out, so has no effect.

@jansohn I'll have a look, it could be that the standard mkdir call includes too wide AccessMask for SMB3. TBH I haven't tested that I think.

rokkakasu commented 3 years ago

Hi @hierynomus yes I too intend to say remove comment and use .withDialects(SMB2Dialect.SMB_3_1_1) . yes please check it may solve my problem #645 also.

Thanks, R Ramarajan.

rokkakasu commented 3 years ago

Hi @hierynomus ,

please share us any update regarding this issue.

thanks, R Ramarajan.

jansohn commented 3 years ago

@vrr6 That is commented out, so has no effect.

@jansohn I'll have a look, it could be that the standard mkdir call includes too wide AccessMask for SMB3. TBH I haven't tested that I think.

@hierynomus I did some further testing. I don't think it is related to the access mask as creating directories works with SMB3 on a Windows Server 2016 share.

The DFS share where it fails is a NetApp FAS9000 share according to our storage guys. I've tried to work-around the DFS resolve issues by directly accessing the resolved share URL. There I get the following stacktrace:

com.hierynomus.mssmb2.SMBApiException: STATUS_ACCESS_DENIED (0xc0000022): Error closing connection to \\server90133.emea.my-company.com\IPC$
    at com.hierynomus.smbj.share.TreeConnect.close(TreeConnect.java:72)
    at com.hierynomus.smbj.share.Share.close(Share.java:115)
    at com.hierynomus.smbj.paths.DFSPathResolver.sendDfsReferralRequest(DFSPathResolver.java:428)
    at com.hierynomus.smbj.paths.DFSPathResolver.step6(DFSPathResolver.java:261)
    at com.hierynomus.smbj.paths.DFSPathResolver.step5(DFSPathResolver.java:222)
    at com.hierynomus.smbj.paths.DFSPathResolver.step2(DFSPathResolver.java:141)
    at com.hierynomus.smbj.paths.DFSPathResolver.step1(DFSPathResolver.java:124)
    at com.hierynomus.smbj.paths.DFSPathResolver.start(DFSPathResolver.java:112)
    at com.hierynomus.smbj.paths.DFSPathResolver.resolve(DFSPathResolver.java:100)
    at com.hierynomus.smbj.share.DiskShare.resolveAndCreateFile(DiskShare.java:105)
    at com.hierynomus.smbj.share.DiskShare.open(DiskShare.java:65)
    at com.company.api.samba.DfsTest.createDirectory(DfsTest.java:90)
    Suppressed: com.hierynomus.mssmb2.SMBApiException: STATUS_ACCESS_DENIED (0xc0000022): Error closing connection to \\server90133.emea.my-company.com\c90133_71$
        at com.hierynomus.smbj.share.TreeConnect.close(TreeConnect.java:72)
        at com.hierynomus.smbj.share.Share.close(Share.java:115)
        at com.company.api.samba.DfsTest.createDirectory(DfsTest.java:100)
        ... 27 more
cliviu commented 3 years ago

Same here : com.hierynomus.mssmb2.SMBApiException: STATUS_ACCESS_DENIED (0xc0000022): Error closing connection to \FILE02\Daten at com.hierynomus.smbj.share.TreeConnect.close(TreeConnect.java:72) ~[smbj-0.11.1.jar:?] at com.hierynomus.smbj.share.Share.close(Share.java:115) ~[smbj-0.11.1.jar:?] at com.hierynomus.smbj.session.Session.logoff(Session.java:236) ~[smbj-0.11.1.jar:?] at com.hierynomus.smbj.session.Session.close(Session.java:279) ~[smbj-0.11.1.jar:?] at com.hierynomus.smbj.connection.Connection.close(Connection.java:168) ~[smbj-0.11.1.jar:?] at com.hierynomus.smbj.connection.Connection.close(Connection.java:145) ~[smbj-0.11.1.jar:?] at com.hierynomus.smbj.SMBClient.close(SMBClient.java:138) [smbj-0.11.1.jar:?]

xarnthehero commented 3 years ago

Reducing the dialect version helped fix this issue for me. Without setting it, we were using 3.1.1 which gave the STATUS_ACCESS_DENIED error on all operations. Reducing it to 3.0 worked.

.withDialects(SMB2Dialect.SMB_3_0)

AlexanderFillbrunn commented 2 years ago

Hi, does smbj "officially" support SMB 3.1.1, making this a bug, or do we have to wait for an implementation of that version? Is the seeming incompatibility related to the encryption coming with SMB 3.1.1 SMB security enhancements?

sathishkumarc14 commented 2 years ago

Hi @jansohn ,

if you are not using NAS share then please try with Version 3_1_1 it works perfectly fine. and use SMBJ Dependency version 0.11.1 or take from master.

Thanks, R Ramarajan.

hierynomus commented 1 year ago

If you turn withEncryptData(true) on, it should now work correctly. This was fixed in #747