miketeo / pysmb

pysmb is an experimental SMB/CIFS library written in Python. It implements the client-side SMB/CIFS protocol (SMB1 and SMB2) which allows your Python application to access and transfer files to/from SMB/CIFS shared folders like your Windows file sharing and Samba folders.
Other
341 stars 94 forks source link

Not supported SMB2 Dialect #95

Open elmosan opened 6 years ago

elmosan commented 6 years ago

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'

miketeo commented 6 years ago

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

elmosan commented 6 years ago

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

miketeo commented 6 years ago

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?

elmosan commented 6 years ago

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?

miketeo commented 6 years ago

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

divad commented 6 years ago

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

miketeo commented 6 years ago

@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 :(

elmosan commented 6 years ago

@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 6 years ago

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 6 years ago

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 6 years ago

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 6 years ago

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.

miketeo commented 6 years ago

@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 6 years ago

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 6 years ago

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.

miketeo commented 6 years ago

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

divad commented 6 years ago

Microsoft included a 'helpful' diagram to explain:

smb dialects

cobolbaby commented 5 years ago

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?

cobolbaby commented 5 years ago

@miketeo

miketeo commented 5 years ago

What is the version of the Samba service?

miketeo commented 5 years ago

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.

malthe commented 3 years ago

@divad did you ever get further with this?

QGB commented 2 years ago

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 2 years ago
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] 远程主机强迫关闭了一个现有的连接。