miketeo/pysmb

Not supported SMB2 Dialect

elmosan opened this issue · 24 comments

Got this error message, when i tried to connect to smb2 server with pysmb==1.1.22:

smb.smb_structs.ProtocolError: Server does not support any of the pysmb dialects. Please email pysmb to add in support for your OS
==================== SMB Message ====================
Command: 0x72 (SMB_COM_NEGOTIATE)
Status: NTSTATUS=0x00000000
Flags: 0x88
Flags2: 0xC003
PID: 10176
UID: 0
MID: 1
TID: 0
Security: 0x0000000000000000
Parameters: 2 bytes
b'ffff'
Data: 0 bytes
b''
==================== SMB Data Packet (hex) ====================
b'ff534d4272000000008803c00000000000000000000000000000c0270000010001ffff0000'

@elmosan : What is the OS of the remote SMB server that you are connecting to?

Sorry forgot to mention, it's a synology dsm 6.1 server with samba

Weird. pysmb does have support for Samba.
Are you able to find out what version of the Samba is running on server, or do a TCP packet capture between your client/server?

The samba version is 4.4.13
Then samba is configured to use SMB2: min protocol=SMB2_10
Do you still need a tcp packet caputre?

@elmosan : Will be good to have the packet capture. I'm using Samba 4.4.16 on my end.

divad commented

This sounds like the Samba server has a weird configuration, like SMB3 only, or pre 'NT' protocol. Can you show the smb.conf?

@divad : I think elmosan's configuration tries to limit the acceptable protocols to a SMB2 version that is only supported by Windows 7 or later. Unfortunately, pySMB does not support the later SMB2 version.

I'm trying to get pysmb to support this later SMB2 version, but isn't making much progress. Samba keeps dropping the authentication attempt by closing the TCP connection with an INVALID code :(

@divad Thanks, it's the protocol. I changed the smb.conf min protocol=SMB2_10 parameter to min protocol=SMB2 and it works now.

The smb parameters are explained here: https://www.samba.org/samba/docs/man/manpages-3/smb.conf.5.html

@miketeo Thanks for your efforts. Ok, I will work with the older SMB2 version for now and hope you can find a way.

edit: Changed because of the reply from miketeo

divad commented

Okay so I found time to look into this, and I think I might have found something interesting. In MS-SMB2 the documentation suggests that the negotiation is quite different between SMB 2.0 and SMB 2.1 (SMB 2.???).

Section 4.1 describes how pysmb is written, with SMB 2 support:

  1. Send SMB COM NEGOTIATE, get response
  2. Send SMB SESSION SETUP, get response
  3. Send SMB TREE CONNECT, get response

However Section 4.2 describes a different approach for SMB 2.1:

  1. Send SMB COM NEGOTIATE, get response
  2. Send SMB COM NEGOTIATE /again/.

This is what pysmb does not do, it proceeds to Session Setup, Samba expects SMB NEGOTIATE again, and so it sends NT_STATUS_INVALID_PARAMETER and closes the session.

According to the docs, the flow is as follows:

  1. The client sends an SMB negotiate packet with the string "SMB 2.???" in the dialect string list,
    along with the other SMB dialects the client implements.
  2. The server receives the SMB negotiate request and finds the "SMB 2.???" string in the dialect
    string list. The server responds with an SMB2 NEGOTIATE Response with the DialectRevision set to
    0x02ff.
  3. The client receives the SMB2 NEGOTIATE Response. The client issues a new SMB2 NEGOTIATE
    Request with a new dialect 0x0210 appended along with other SMB2 dialects.
  4. The server receives the SMB2 negotiate request and finds dialect 0x0210. The server sends an
    SMB2 NEGOTIATE Response with DialectRevision set to 0x0210.

Now, it could be you already know this and I'm barking up the wrong tree, in which case, sorry! If that is the case, can I see the code you've written to do the above, so I can try to figure out what other error you're seeing?

divad commented

Yes, so this is the issue. What we need to do is:

  1. Send SMB COM NEGOTIATE, get response
  2. Send SMB2 NEGOTIATE, get response

I'm writing an implementation of SMB2 NEGOTIATE now, but I've never dabbled at this level before, so it may take me some time xD

divad commented

I have a working implementation of SMB2 COM NEGOTIATE and I can now, with pysmb, connect to SMB servers using the 2.1 dialect.

However, now I'm getting weird errors after connecting, wireshark insists that pysmb is trying to open a file called "(" (????). Its all very confusing. I'll keep working on it!

divad commented

Right, the problem is credits. With SMB 2.1 enabled (which actually is SMB2 proper, really), the client must request credits. pysmb does not, and so the server gets angry.

@divad : Many thanks for identifying the problem for SMB 2.1 in pysmb. I will have to read up the credits sections in [MS-SMB2] again. The dual NEGOTIATE requests really sound like an Easter egg in the specifications.

divad commented

Yup. Would you like me to send the work I've done so far, even if incomplete? I'll create a branch and share it with you a bit later today.

divad commented

I was gonna read this repo in depth: https://github.com/hirochachacha/go-smb2

Its a working SMB2/3 client, with credits support. Its Go, so its quite easy to follow. It has a fully implemented credits solution.

@divad : (code-sharing) Yes, please. Will be useful when I have the time to work on this.

divad commented

Microsoft included a 'helpful' diagram to explain:

smb dialects

I launch the samba service in docker container dperson/samba. However, when I connect the service using pysmb, Exception Server does not support any of the pysmb dialects. Please email pysmb to add in support for your OS always is thrown.

What should I do next?

What is the version of the Samba service?

You can try editing the smb.conf file and change (or add if necessary) this parameter:
server min protocol = LANMAN1

Remember to restart the samba service after the change.

@divad did you ever get further with this?

QGB commented

C:\QGB\Anaconda3\lib\site-packages\smb\smb_structs.py in decode(self, message)
    360         elif self.dialect_index == 0xFFFF:
    361             raise ProtocolError('Server does not support any of the pysmb dialects. Please email pysmb to add in support for your OS',
--> 362                                 message.raw_data, message)
    363         else:
    364             raise ProtocolError('Unknown dialect index (0x%04X)' % self.dialect_index, message.raw_data, message)

ProtocolError: Server does not support any of the pysmb dialects. Please email pysmb to add in support for your OS
==================== SMB Message ====================
Command: 0x72 (SMB_COM_NEGOTIATE)
Status: NTSTATUS=0x00000000
Flags: 0x88
Flags2: 0xC003
PID: 6672
UID: 0
MID: 1
TID: 0
Security: 0x0000000000000000
Parameters: 2 bytes
b'ffff'
Data: 0 bytes
b''
==================== SMB Data Packet (hex) ====================
b'ff534d4272000000008803c00000000000000000000000000000101a0000010001ffff0000'

QGB commented
In [134]: conn.connect('192.168.1.3',445)
---------------------------------------------------------------------------
ConnectionResetError                      Traceback (most recent call last)
<ipython-input-134-b35ca093384e> in <module>
----> 1 conn.connect('192.168.1.3',445)

C:\QGB\Anaconda3\lib\site-packages\smb\SMBConnection.py in connect(self, ip, port, sock_family, timeout)
    125                 self.onNMBSessionOK()
    126             while self.auth_result is None:
--> 127                 self._pollForNetBIOSPacket(timeout)
    128         finally:
    129             self.is_busy = False

C:\QGB\Anaconda3\lib\site-packages\smb\SMBConnection.py in _pollForNetBIOSPacket(self, timeout)
    611                         raise ex
    612                 else:
--> 613                     raise ex
    614
    615         type, flags, length = struct.unpack('>BBH', data)

C:\QGB\Anaconda3\lib\site-packages\smb\SMBConnection.py in _pollForNetBIOSPacket(self, timeout)
    600                     raise SMBTimeout
    601
--> 602                 d = self.sock.recv(read_len)
    603                 if len(d) == 0:
    604                     raise NotConnectedError

ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。