12.1 The SMB_HEADER.STATUS Field Exposed

12.1 The SMB_HEADER.STATUS Field Exposed

Things get interesting starting at the STATUS field. It wouldn't be so bad except for the fact that there are two possible error code formats to consider. There is the DOS and OS/2 format, and then there is the NT_STATUS format. In C language terms, the STATUS field looks something like this:

 typedef union   {   ulong NT_Status;   struct     {     uchar  ErrorClass;     uchar  reserved;     ushort ErrorCode;     } DosError;   } Status; 

From the client side, one way to deal with the split personality problem is to use the DOS codes exclusively. [1] These are fairly well documented (by SMB standards), and should be supported by all SMB servers. Using DOS codes is probably a good choice, but there is a catch... there are some advanced features which simply don't work unless the client negotiates NT_STATUS codes.

[1] This is exactly what jCIFS does (up through release 0.6.6 and the 0.7.0beta series). There has been a small amount of discussion about supporting the NT_STATUS codes, but it's not clear whether there is any need to change.

Strange Behavior Alert

graphics/alert.gif

If the client negotiates Extended Security with a Windows 2000 server and also negotiates DOS error codes, then the SESSION SETUP ANDX will fail, and return a DOS hardware error. (!?)

 STATUS   {   ErrorClass = 0x03   (Hardware Error)   ErrorCode  = 0x001F (General Error)   } 

Perhaps W2K doesn't know which DOS error to return, and is guessing. The bigger question is, why does this fail at all?

The same SMB conversation with the NT_STATUS capability enabled works just fine. Perhaps, when the coders were coding that piece of code, they assumed that only clients capable of using NT_STATUS codes would also use the Extended Security feature. Perhaps that assumption came from the knowledge that all Windows systems that could handle Extended Security would negotiate NT_STATUS. We can only guess...

This is one of the oddities of SMB, and another fine bit of forensic SMB research by Andrew Bartlett of the Samba Team.


Another reason to support NT_STATUS codes is that they provide finergrained diagnostics, simply because there are more of them defined than there are DOS codes. Samba has a fairly complete list of the known NT_STATUS codes, which can be found in the samba/source/include/nterr.h file in the Samba distribution. The list of DOS codes is in doserr.h in the same directory.

We have already described the structure of the DOS error codes. NT_STATUS codes also have a structure, and it looks like this:

graphics/199fig01.gif

In testing, it appears as though the Facility field is always set to zero ( FACILITY_NULL ) for SMB errors. That leaves us with the Level and ErrorCode fields to provide variety... and, as we have suggested, there is quite a bit of variety. Samba's nterr.h file lists over 500 NT_STATUS codes, while doserr.h lists only 99 (and some of those are repeats).

Level is one of the following:

00 == Success

01 == Information

10 == Warning

11 == Error

Since the next two bits (the <reserved> bits) are always zero, the highestorder nibble will have one of the following values: 0x0 , 0x4 , 0x8 , or 0xC . At the other end of the longword, the ErrorCode is read as an unsigned short (just like the DOS ErrorCode field).

The availability of Samba's list of NT_STATUS codes makes things easy. It took a bit of effort to generate that list, however, as most of the codes are not documented in an accessible form. Andrew Tridgell described the method below, which he used to generate a list of valid NT_STATUS codes. His results were used to create the nterr.h file used in Samba.

Tridge's Trick

graphics/hat.gif
  1. Modify the source of Samba's smbd daemon so that whenever you try to delete a file that matches a specific pattern it will return an NT_STATUS error code. (Do this on a testing copy, of course. This hack is not meant for production.) For example, return an error whenever the filename to be deleted matches " STATUS_CODE_HACK_FILENAME.* ". Another thing to do is to include the specific error number as the filename extension, so that the name

     STATUS_CODE_HACK_FILENAME.0xC000001D 

    will cause Samba to return an NT_STATUS code of 0xC000001D .

  2. Create the files on the server side first so you have something to delete. That is easily done with a shell script, such as this:

     #!/bin/bash # i=0;j=256 while [ $i -lt $j ] do  touch `printf "STATUS_CODE_HACK_FILENAME.0xC000%.4x" $i`  i=`expr $i + 1` done 

    Change the values of i and j to generate different ranges.

  3. On a Windows NT or Windows 2000 system, mount the Samba share containing the generated STATUS_CODE_HACK* files. Next, open a DOS command shell and, one by one, delete the files. For each file, Samba should return the specified NT_STATUS code... and Windows will interpret the code and tell you what it means. If the code is not defined, Windows will tell you that as well.

  4. If you capture the delete transactions using Microsoft's NetMon tool, it will show you the symbolic names that Microsoft uses for the NT_STATUS codes.


Okay, now for the next conundrum ...

Servers have it tougher than clients. Consider a server that needs to respond to one client using DOS error codes, and to another client using NT_STATUS codes. That's bad enough, but consider what happens when that server needs to query yet another server in order to complete some operation. For example, a file server might need to contact a Domain Controller in order to authenticate the user .

The problem is that, no matter which STATUS format the Domain Controller uses when responding to the file server, it will be the wrong format for one of the clients. To solve this problem the server needs to provide a consistent mapping between DOS and NT_STATUS codes.

Windows NT and Windows 2000 both have such mappings built-in but, of course, the details are not published (a partial list is given in Section 6 of the SNIA doc). Andrew Bartlett used a trick similar to Tridge's in order to generate the required mappings. His setup uses a Samba server running as a Primary Domain Controller (PDC), and a Windows 2000 system providing SMB file services. A third system, running Samba's smbtorture testing utility, acts as the client. When the client system tries to log on to the Windows server, Windows passes the login request to the Samba PDC.

The test works like this:

Andrew Bartlett's Trick

graphics/hat.gif
  1. Modify Samba's authentication code to reject login attempts for any username beginning with " 0x ". Translate the login name (e.g. " 0xC000001D ") into an NT_STATUS code, and return that in the STATUS field.

  2. Configure smbtorture to negotiate DOS error codes. Aim smbtorture at the W2K SMB server and try logging in as user 0xC0000001 , 0xC0000002 ... etc.

  3. For each login attempt from the client, the Windows SMB server will receive a login failure message from the Samba PDC. Since smbtorture has requested DOS error codes, the W2K pickle -in-the-middle is forced to translate the NT_STATUS values into DOS error codes... and that's how you discover Microsoft's mapping of NT_STATUS codes to DOS error codes.

    The test configuration is shown in Figure 12.1.

    Figure 12.1. Andrew Bartlett's test configuration

    The polite way to ask Windows for its NT_STATUS-to-DOS error code mappings.

    The client sends a logon request to the W2K server, which forwards it to the Samba PDC. The PDC rejects the login, using the Username as the NT_STATUS code. The client requested DOS error codes, so the W2K system must translate.

    graphics/12fig01.gif


Andrew's test must be rerun periodically. The mappings have been known to change when Windows service packs are installed. See the file samba/source/libsmb/errormap.c in the Samba distribution for more fun and adventure. [2]

[2] After all that work... Sometime around August of 2002, Microsoft posted a bit of documentation listing the DOS error codes that they have defined. Not all are used in CIFS, but it's a nice list to have. In addition, they have documented an NTDLL.DLL function that converts DOS error codes into NT_STATUS codes. (Thanks to Jeremy for finding these.)



Implementing CIFS. The Common Internet File System
Implementing CIFS: The Common Internet File System
ISBN: 013047116X
EAN: 2147483647
Year: 2002
Pages: 210

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net