Smb2-protocol: [Smb2-protocol] a first look at SMB2

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

Date: Thu, 24 Nov 2005 14:53:06 +1100
I thought the following might be useful for people interested in the
changes in SMB2 as compared to SMB.

Cheers, Tridge

---

SMB2 protocol - first impressions
---------------------------------

This is a quick summary of what we have found out so far about the
SMB2 protocol. We've been analysing/implementing it for a couple of
weeks now and are at the stage where the main features of the protocol
are mapped out. 

Credits
-------

Many thanks to Ronnie Sahlberg for all his efforts on the SMB2
ethereal dissector. Also thanks to Stefan Metzmacher and Steve
French for working out some important parts of the packet formats, and
to Stefan for helping with the initial implementation of SMB2 in
Samba4. 

New Packet Format
-----------------

The most obvious change is that SMB2 has a new packet format. The
header includes much of the same information as the old format, but
with wider fields, and a different layout. The new header is
substantially larger than the old one (64 bytes versus 35 bytes),
mostly caused by the wider fields. At least its nicely aligned now!

Fewer Commands
--------------

The number of top level commands has been greatly reduced, and is down
to 18 opcodes. Where SMB had a pile of different ways for doing
something, SMB2 has just one, which is a nice change. The commands
that we have found in SMB2 are

NEGPROT   0x00
SESSSETUP 0x01
unknown   0x02
TCON      0x03
TDIS      0x04
CREATE    0x05
CLOSE     0x06
unknown   0x07
READ      0x08
WRITE     0x09
unknown   0x0A
mount?    0x0B
CANCEL    0x0c
unknown   0x0d
FIND      0x0e
NOTIFY    0x0f
GETINFO   0x10
SETINFO   0x11
BREAK     0x12


so there are still 5 commands we haven't worked out yet, volunteers to
work these out are welcome. 

Each of the commands has a quite different structure to the equivalent
SMB commands, but the individual fields and their meanings are very
familiar to anyone who has dealt closely with SMB. So for example, the
CREATE opcode uses quite a different layout to the SMB NTCreateX
operations, but once you map the fields across, the meaning of each
bit remains the same.

Handle Oriented
---------------

One interesting change is that SMB2 is much more handle oriented than
SMB. So for example, in SMB2 the FIND command takes a handle, as does
the GETINFO command, even when used for filesystem queries (such as
disk space). We saw the beginnings of this trend with recent
implementation changes in the old SMB protocol from Microsoft, where
the 'path' varients of the trans2 queryinfo calls were used less and
less and applications started to delete files by first opening with
delete on close then closing. The changes in SMB2 continue this trend,
by removing all the non-handle based calls. 

In a similar style, there is no 'mkdir', 'unlink' or similar path
based commands, instead CREATE is always used to get a handle then a
close is used if the handle is not needed. The handle size has also
grown a lot. It was just 16 bits in SMB, and has become 128 bits in
SMB2.

The use of a handle in FIND is particularly interesting, especially as
vista clients ask for oplocks when opening the handles to be used for
listing files. I haven't yet checked to see if oplocks on these
handles trigger oplock breaks, but if they do then it would provide an
potentially big improvement in the cache coherency mechanisms for
directories. Other filesystem protocols have had this type of thing
for a while, so I would not be surprised for it to be used in this way
in SMB2.

Info Levels
-----------

Anyone who spends much time with SMB soon learns the importance of
knowing your 'information levels'. These are still there in SMB2, and
in fact SMB2 seems to use exactly the same structure layout for almost
all information levels, just numbering them differently. So the old
SMB findfirst level 0x106 which we called
SMB_FIND_ID_BOTH_DIRECTORY_INFO is exactly the same as the SMB2 FIND
level 0x25. This makes sharing code between a SMB and SMB2
implementation particularly easy, as quite a large amount of the base
protocol code deals with these info levels.

One notable exception is the ALL_INFORMATION query file information
level from SMB (level 0x107 and its passthru alias at 1018), which is
cloest to the SMB2 GETINFO fileinfo level 18. All the other SMB2
GETINFO levels are just the old SMB passthru levels minus 1000 with
the same structures, but the ALL_INFORMATION level contains 4 extra
fields not included in the SMB level (the file_id, the access_mask,
the position and mode).

The use of the old layouts for nearly all information levels does lead
to some strange anachronisms. For example, the levels that query EAs
still use ASCII for the EA labels, even though all the rest of SMB2
uses UTF16.

Negotiation
-----------

The SMB2 protocol is negotiated using the SMB protocol varient string
"SMB 2.001".  Once the vista client knows the server can do SMB2 it
opens an entirely new TCP socket to the server, and launches into
SMB2, which uses the marker 0xFE 'S' 'M' 'B' instead of the old 0xFF
'S' 'M' 'B'.

The client seems to remember the fact that a particular server does
SMB2, and skips the SMB negotiation stage in future connections (until
a reboot).

Chaining and Transactions
-------------------------

According to a Microsoft blog entry the SMB2 protocol includes
filesystem transaction support and expanded command chaining. Thus far
we haven't seen any evidence of these in the traffic we have looked
at, but that is probably just a result of the vista client not taking
advantage of these features yet.

I certainly expect that the client will start to use chaining at some
stage, as the reduction in the number of SMB commands means that the
protocol becomes much less efficient than SMB was unless you use
chaining. For example, the DCE/RPC was mostly carried on top of the
old SMBtrans request, which is essentially a "write+read"
operation. In SMB2 a separate write and read operation is used, which
doubles the number of requests. This could easily be fixed with
chaining. 

More Information
----------------

The ethereal wiki at http://wiki.ethereal.com/SMB2 has a lot of good
information, and the latest svn revisions of ethereal include enough
support for parsing SMB2 to be very useful.

The Samba4 svn includes a basic client library, and a test suite for
some of the operations. Look in source/libcli/smb2/ and torture/smb2/
for details.

I'd particularly recommend looking at some of the network captures in
the ethereal SMB2 wiki pages using a current version of ethereal. This
is a way to quickly get a feel for the protocol.