hierynomus / smbj

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

Is the functionality to list all file shares in an SMB location implemented yet? #600

Open Sagar-Singari opened 3 years ago

Sagar-Singari commented 3 years ago

@hierynomus hierynomus Need to list all shares in a SMB location. It gives null pointer error when I try to do it.

Is the functionality implemented yet?

Thanks!

hierynomus commented 3 years ago

Hi @bobsag,

Listing all shares is done using an RPC call and has been implemented in https://github.com/rapid7/smbj-rpc

Do note that this is pretty old, and does not work with the current master anymore.

It might be worth porting this into smbj, but I could definitely use some help there ;)

chrisgch commented 3 years ago

I'm asking this here because the last activity in smbj-rpc was 2 years ago.

smbj-rpc does work for me as long as I don't use encrypted SMB3. If I use SMB3 via the call config = SmbConfig.builder().withDialects(SMB2Dialect.SMB_3_1_1, SMB2Dialect.SMB_3_0_2, SMB2Dialect.SMB_3_0, SMB2Dialect.SMB_2_1, SMB2Dialect.SMB_2_0_2).withMultiProtocolNegotiate(true).build(); then I get VERY strange behaviour: To list shares, the client connects to IPC$ by sending SMB2_TREE_CONNECT, then SMB2_CREATE, then SMB2_IOCTL. The first two of these can be sent encrypted. But when I send the 3rd encrypted, I get back STATUS_INVALID_PARAMETER error (0XC000000D). When I send the first two encrypted and the last unencrypted by changing the function send(SMB2Packet packet) in Session.java from if (shouldEncryptData()) to if (shouldEncryptData() && !packet.getHeader().getMessage().equals(SMB2MessageCommandCode.SMB2_IOCTL)) then the RPC call goes through just fine, and I get the list of shares. Of course this doesn't work when I disallow unencrypted data on the server side via Powershell: $Set-SmbServerConfiguration -EncryptData $true

So does anyone have an idea why the SMB2_IOCTL packet cannot be sent encrypted? This doesn't make any sense to me.

nddipiazza commented 3 years ago

For others who find this via google search, example of listing shares using the dcerpc module:

add dep

<dependency>
  <groupId>com.rapid7.client</groupId>
  <artifactId>dcerpc</artifactId>
  <version>0.10.0</version>
</dependency>

Usage:

final SMBClient smbClient = new SMBClient();
try (final Connection smbConnection = smbClient.connect("www.yyy.xxx.zzz")) {
    final AuthenticationContext smbAuthenticationContext = new AuthenticationContext("username", "password".toCharArray(), "domain");
    final Session session = smbConnection.authenticate(smbAuthenticationContext);

    final RPCTransport transport = SMBTransportFactories.SRVSVC.getTransport(session);
    final ServerService serverService = new ServerService(transport);
    final List<NetShareInfo0> shares = serverService.getShares();
    for (final NetShareInfo0 share : shares) {
        System.out.println(share);
    }
}

Sounds like this issue should be closed, and a new Issue should be created about the SMB3 support.

DaveBoy commented 3 years ago

smbj-rpc can list all file shares(or more),but it just support smbj 0.10.0. i don't know what's new in 0.11.1

DaveBoy commented 3 years ago

i found that smbj-0.11.1 delete this method:Connection.getConfig and smbj-rpc use this method,it make this exception

DaveBoy commented 3 years ago

smbj-rpc i have change some new api call in smbj-rpc to support smbj-0.11.1. i hope it can help others who find this via google search.

BerndHafenrichter commented 2 years ago

Dear hierynomus, Dear team,

i'a also struggle with problem discussed in this stream.. I am using a smb-server that uses DFS. When i use to protocol dialect 3.1.1 i always get a null-pointer exception when is try get access to an file that resides in the dfs shar. Everything works well when i change the smb dialect to 3.0.2. In my detail investigation i found out that the problem arises when the method DFSPathResolver.getReferral submits the IOCTL-Command in oder to resolve the referrer. The returned response packet always returns the status code INVALID_PARAMETER. As i mentioned before, everything works fine when using 3.0.2. I also tested to send the IOCT-Message unencrypted. Also this worked well.

On basis of this observations i started a deeper investigation of the problem. I had a look at the configuration, negotiation results and so on. The only difference that i found out is, that in 3.1.1 a individual encryption algorithm is used instead of the standard algorithm that is used when dealing with 3.0.2.

The behavior is still not clear to me, since the marshaling/unmarshaling is still the same independent of the dialect. Together with the above mention status code it think that the problem is somewhere around the encryption logic. I'am sorry but i was not able to figure out the problem completely.

Do you need any information to reproduce the problem?

hierynomus commented 2 years ago

I think that the problem is that dialect 3.1.1 has added a parameter or something to the ioctl. I need to dive into the spec to find that.

BerndHafenrichter commented 2 years ago

Dear hierynomus, Dear team,

i think i have found the problem with smb 3.1.1 and dfs. The reason is, that the getMaxPayloadSize() is not computed properly when an encrypted packet is sent. Due to the specification, the smb-server has to check the credits (if an IOCTL-Messsage is sent), which are based on the getMaxPayloadSize() of the transferred packet. In case when an encrypted packet was sent, the result for getMaxPayloadSize() of the wrapped packet was always SINGLE_CREDIT_PAYLOAD_SIZE since the method getMaxPayloadSize() was not overwritten. This lead to a wrong handling of the credits, which in consequence lead to an INVALID_PARAMETER when the IOCTL-Message was sent. If the getMaxPaloadSize is overwritten (the same is done in SignedPacketWarpper) the dfs-access with 3.1.1 works as expected:

You can see my changes in the following code fragment:

public class EncryptedPacketWrapper extends SMB2Packet {

    @Override
    public int getMaxPayloadSize() {
        return packet.getMaxPayloadSize();
    }}

The reason why it works ( as described by chrisgch ) is, that the packet is sent unencrypted. In this case. the SignedPacketWrapper is used to send the IOCTL-Messages. Since this class overwrites the getMaxPayloadSize() method as described above it works as expected.

I hope my diagnosis helps.

Best regards Bernd

hierynomus commented 2 years ago

Hi Bernd, Thanks for the analysis! I've just made a PR with the change in #683. If that builds OK, I will merge it and this should be fixed.