Bug 6911 - Kerberos authentication from vista to samba fails when security blob size is greater than 16 kB
Kerberos authentication from vista to samba fails when security blob size is ...
Status: RESOLVED FIXED
Product: Samba 3.3
Classification: Unclassified
Component: File services
3.3.9
Sparc Solaris
: P3 major
: ---
Assigned To: Karolin Seeger
Samba QA Contact
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2009-11-20 09:08 UTC by Florian Kudermann
Modified: 2011-05-29 17:57 UTC (History)
1 user (show)

See Also:


Attachments
wireshark capture of session setup of user with 1000 groups. (140.78 KB, application/octet-stream)
2011-05-24 18:08 UTC, Jim McDonough
no flags Details
pcap of samba 3.5.8 failling on secblob too big (660 bytes, application/octet-stream)
2011-05-26 21:17 UTC, Jim McDonough
no flags Details
pcap of samba 3.5.8 failling on secblob too big (35.68 KB, application/octet-stream)
2011-05-26 21:27 UTC, Jim McDonough
no flags Details
git-am fix for 3.5.next (2.65 KB, patch)
2011-05-26 23:43 UTC, Jeremy Allison
jmcd: review+
Details
git-am fix for 3.6.0 (2.64 KB, patch)
2011-05-27 00:10 UTC, Jeremy Allison
jmcd: review+
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Florian Kudermann 2009-11-20 09:08:19 UTC
Samba 3.3.9 (and other versions too) fail to verify Kerberos authentication
of a SMB Session Setup from _Vista_ (or Server 2008) CIFS clients, if 
the Kerberos ticket size is  greater then 16KB.

(Which may happen, if the connecting account is member of lots of security
groups (> 500) and the windows domain is configured to create tickets > 12Kb)

Kerberos authentications (with tickets > 16KB) from _Win2k3_ CIFS Clients to the same Samba Server are accepted on the other hand.

Error messages:

With Samba 3.3.9:

[2009/11/20 13:55:51,  3] [2009/11/20 13:55:51,  3] libads/kerberos_verify.c:ads_verify_ticket(471)
  ads_verify_ticket: krb5_rd_req with auth failed (ASN.1 encoding ended unexpectedly)
[2009/11/20 13:55:51,  1] smbd/sesssetup.c:reply_spnego_kerberos(350)
  Failed to verify incoming ticket with error NT_STATUS_LOGON_FAILURE!
[2009/11/20 13:55:51,  3] smbd/error.c:error_packet_set(61)
  error packet at smbd/sesssetup.c(352) cmd=115 (SMBsesssetupX) NT_STATUS_LOGON_FAILURE


With Samba 3.4.3 or 3.0.37 I got:

[2009/11/17 10:41:19,  1] libsmb/clispnego.c:293(parse_negTokenTarg)               Failed to parse negTokenTarg at offset 4

These reported error messages seem to be correct,
the reason for this is:
If the "Session Setup AndX Request" is > 16kb,  it gets segmented into 2 parts:

The first part gets answered with a  "Session Setup andX Response": STATUS_MORE_PROCESSING_REQUIRED.

Then the cifs client should send the second part with another
"Session Setup AndX Request".

If VISTA is the connecting client, the second part is NOT send, but instead
Vista resends the first part again.

Samba concats both parts and gets a screwed, unparsable request with the resulting error messages.

If the client is Win2k3, it just sends the second part and Samba is able to
accept the request.

The question is, why is the first part of the "Session Setup AndX Request" resent in the Vista case?

I compared a network trace from Vista client to a Win2K2 server with the errornous Vista to Samba trace and noticed this difference in the first 
"Session Setup AndX Response" packet:


Win2k3 to Vista Session Setup Response Packet:
==============================================

Frame 504 (229 bytes on wire, 229 bytes captured)
Ethernet II, Src: Cisco_93:5c:40 (00:19:a9:93:5c:40), Dst: FujitsuT_64:90:25 (00:19:99:64:90:25)
Internet Protocol, Src: win2k3_server (147.56.33.91), Dst: vista_client (147.59.44.20)
Transmission Control Protocol, Src Port: microsoft-ds (445), Dst Port: 53107 (53107), Seq: 193, Ack: 16677, Len: 175
NetBIOS Session Service
SMB (Server Message Block Protocol)
    SMB Header
        Server Component: SMB
        [Response to: 500]
        [Time from request: 0.000694000 seconds]
        SMB Command: Session Setup AndX (0x73)
        NT Status: STATUS_MORE_PROCESSING_REQUIRED (0xc0000016)
        Flags: 0x98
        Flags2: 0xc807
        Process ID High: 0
        Signature: 4253525350594C20
        Reserved: 0000
        Tree ID: 65535  (\\win2k3_server\TEST)
        Process ID: 65279
        User ID: 16385
        Multiplex ID: 64
    Session Setup AndX Response (0x73)
        Word Count (WCT): 4
        AndXCommand: No further commands (0xff)
        Reserved: 00
        AndXOffset: 171
        Action: 0x0000
        Security Blob Length: 0
        Byte Count (BCC): 128
        Security Blob: <MISSING>
        Native OS: Windows Server 2003 3790 Service Pack 2
        Native LAN Manager: Windows Server 2003 5.2




Samba to Vista Session Setup Response:
======================================

Frame 42 (93 bytes on wire, 93 bytes captured)
Ethernet II, Src: SunMicro_b1:49:00 (00:14:4f:b1:49:00), Dst: All-HSRP-routers_35 (00:00:0c:07:ac:35)
Internet Protocol, Src: samba_server (147.56.32.18), Dst: vista_client (147.59.44.20)
Transmission Control Protocol, Src Port: microsoft-ds (445), Dst Port: 50576 (50576), Seq: 208, Ack: 16677, Len: 39
NetBIOS Session Service
SMB (Server Message Block Protocol)
    SMB Header
        Server Component: SMB
        [Response to: 40]
        [Time from request: 0.002659000 seconds]
        SMB Command: Session Setup AndX (0x73)
        NT Status: STATUS_MORE_PROCESSING_REQUIRED (0xc0000016)
        Flags: 0x88
        Flags2: 0xc801
        Process ID High: 0
        Signature: 0000000000000000
        Reserved: 0000
        Tree ID: 65535
        Process ID: 65279
        User ID: 0
        Multiplex ID: 64
    Session Setup AndX Response (0x73)
        Word Count (WCT): 0
        Byte Count (BCC): 0



The "Session Setup AndX Response (0x73)" part is much shorter
if Samba is answering, compared to the Win2k3 Server.

Is this difference the cause for Vista reacting differently to the first 
Session Setup AndX Response packet?

I think something is buggy here :)
Thanks




Samba Setup is:

./configure --prefix=$DIR/versions/$PLATFORM/$VERSION  --localstatedir=$DIR  --with-privatedir=$DIR/private  --with-logfilebase=$DIR/log  --with-configdir=$DIR/etc --disable-cups --with-ldap --with-ads --with-pam 

libiconv-1.13.1, krb5-1.7, openssl-0.9.8l, openldap-2.4.19, samba-3.3.9
Solaris 10, 64 Bit build. built with gcc 4.4.2



smb.conf
[global]
   security = ADS
   encrypt passwords = Yes
   read only = no
   workgroup = XXX
   netbios name = SAMBA_SERVER
   realm = XXX.YYY.ZZZ
   interfaces = 147.56.32.18/20
   bind interfaces only = yes
   log level = 5
   unix charset = ISO-8859-1
   display charset = ISO-8859-1
   map to guest = Bad Uid
   passdb expand explicit = no
   hide files = /desktop.ini/@GMT-*/~*/
   admin users = +smbadmin
   msdfs root = yes
Comment 1 Jim McDonough 2011-05-24 17:33:27 UTC
It has been proposed by IBM that the problem is in asn1_tag_remaining(). I haven't had a chance to review the specifics yet, but the general location is correct:

"I believe the problem is due to a defect in asn1_tag_remaining(). 
check_spnego_blob_complete() is called to confirm whether or not the security
blob received is complete or not.  It sets the pointers in the data structure
in asn1_start_tag():

        nesting->start = data->ofs;
        nesting->next = data->nesting;
        data->nesting = nesting;

Then in asn1_tag_remaining() those pointers are used:

        remaining = data->nesting->taglen - (data->ofs - data->nesting->start);
        if (remaining > (data->length - data->ofs)) {
                data->has_error = true;
                return -1;
        }
        return remaining;

If I am following the pointers correctly, data->nesting->start = data->ofs.  In
which case, remaining will always evaluate to data->nesting->taglen, which will
always be greater than data->length - data->ofs.  As a result, 
asn1_tag_remaining() will always return an error causing
check_spnego_blob_complete() to return NT_STATUS_OK instead of
NT_STATUS_MORE_PROCESSING_REQUIRED.  This causes the packet to be parsed as a
full security blob, which fails and leads to a login failure error.

In the 3.0.32 version of Samba, the asn1_tag_remaining() function does not
exist, so this problem doesn't occur.

My guess is that the fix would be to repair asn1_tag_remaining() to be something along the lines of:

     remaining = data->nesting->taglen - (data->length - data->ofs);"
Comment 2 Jim McDonough 2011-05-24 17:38:10 UTC
(In reply to comment #1)
> My guess is that the fix would be to repair asn1_tag_remaining() to be
> something along the lines of:
> 
>      remaining = data->nesting->taglen - (data->length - data->ofs);"
At first glance, I suspect this is not right, as this function is used in a more general case than just spnego.

More likely we need to not fail the logon with an ASN.1 failure. but rather fail only the offered method, and fall back to NTLMSSP (as this is actually what windows is doing...it's not getting more of the ticket in subsequent packets, it's giving the NTLM challenge in the MORE_PROCESSING_REQUIRED response.
Comment 3 Jim McDonough 2011-05-24 18:08:49 UTC
Created attachment 6483 [details]
wireshark capture of session setup of user with 1000 groups.

192.168.213.162 is the windows XP client
192.168.213.10 is the 2k3R2 DC and file server

session setup fully reassembled is in frame 127.  It's kerberos...
Comment 4 Jim McDonough 2011-05-26 21:17:16 UTC
Created attachment 6489 [details]
pcap of samba 3.5.8 failling on secblob too big
Comment 5 Jim McDonough 2011-05-26 21:27:08 UTC
Created attachment 6490 [details]
pcap of samba 3.5.8 failling on secblob too big
Comment 6 Jim McDonough 2011-05-26 21:48:14 UTC
Watchpoint 3: data->has_error

Old value = false
New value = true
asn1_tag_remaining (data=0x7ffff82be660) at ../lib/util/asn1.c:541
541			return -1;
(gdb) where
#0  asn1_tag_remaining (data=0x7ffff82be660) at ../lib/util/asn1.c:541
#1  0x00007ffff7856e64 in asn1_start_tag (data=0x7ffff82be660, tag=<value optimized out>) at ../lib/util/asn1.c:497
#2  0x00007ffff78548b8 in parse_negTokenTarg (blob=..., OIDs=0x7fffffffd470, secblob=0x7fffffffd5f0) at libsmb/clispnego.c:293
#3  0x00007ffff77e6026 in parse_spnego_mechanisms (blob_in=..., pblob_out=<value optimized out>, kerb_mechOID=0x7fffffffd680) at smbd/sesssetup.c:728
#4  0x00007ffff77e7b1d in reply_spnego_negotiate (req=0x7ffff82be340) at smbd/sesssetup.c:797
#5  reply_sesssetup_and_X_spnego (req=0x7ffff82be340) at smbd/sesssetup.c:1303
#6  reply_sesssetup_and_X (req=0x7ffff82be340) at smbd/sesssetup.c:1457
#7  0x00007ffff781efb5 in switch_message (type=115 's', req=0x7ffff82be340, size=16626) at smbd/process.c:1404
#8  0x00007ffff781f357 in construct_reply (conn=0x7ffff82364c0, inbuf=<value optimized out>, nread=16626, unread_bytes=0, seqnum=0, encrypted=false, deferred_pcd=0x0)
    at smbd/process.c:1436
#9  process_smb (conn=0x7ffff82364c0, inbuf=<value optimized out>, nread=16626, unread_bytes=0, seqnum=0, encrypted=false, deferred_pcd=0x0) at smbd/process.c:1509
#10 0x00007ffff781f7d1 in smbd_server_connection_read_handler (ev=<value optimized out>, fde=<value optimized out>, flags=<value optimized out>, private_data=<value optimized out>)
    at smbd/process.c:2126
#11 smbd_server_connection_handler (ev=<value optimized out>, fde=<value optimized out>, flags=<value optimized out>, private_data=<value optimized out>) at smbd/process.c:2141
#12 0x00007ffff7a3f42b in run_events (ev=0x7ffff8236400, selrtn=1, read_fds=0x7fffffffdac0, write_fds=0x7fffffffda40) at lib/events.c:157
#13 0x00007ffff7820e25 in smbd_server_connection_loop_once () at smbd/process.c:844
#14 smbd_process () at smbd/process.c:2455
#15 0x00007ffff7d2ced5 in smbd_accept_connection (ev=<value optimized out>, fde=<value optimized out>, flags=<value optimized out>, private_data=<value optimized out>)
    at smbd/server.c:391
#16 0x00007ffff7a3f42b in run_events (ev=0x7ffff8236400, selrtn=1, read_fds=0x7fffffffdea0, write_fds=0x7fffffffde20) at lib/events.c:157
#17 0x00007ffff7a3f623 in s3_event_loop_once (ev=0x7ffff8236400, location=<value optimized out>) at lib/events.c:220
#18 0x00007ffff7a400c0 in _tevent_loop_once (ev=0x7ffff8236400, location=0x7ffff7f3bc7c "smbd/server.c:743") at ../lib/tevent/tevent.c:497
#19 0x00007ffff7d2db43 in smbd_parent_loop (argc=<value optimized out>, argv=<value optimized out>) at smbd/server.c:743
Comment 7 Jeremy Allison 2011-05-26 23:43:43 UTC
Created attachment 6491 [details]
git-am fix for 3.5.next

Jim - please check this patch (but I'm 100% convinced it's right :-). I'll create a patch for 3.6.0 as well as this affects all releases.

Jeremy.
Comment 8 Jeremy Allison 2011-05-26 23:52:07 UTC
Jim, you should be able to reproduce the Windows -> windows spnego split of 4k by setting the parameter:

max xmit = 4356

(which is what Windows uses) in the [global] section of your smb.conf.

Jeremy.
Comment 9 Jeremy Allison 2011-05-27 00:10:05 UTC
Created attachment 6492 [details]
git-am fix for 3.6.0

Same fix for 3.6.0.

Jeremy.
Comment 10 Jim McDonough 2011-05-27 02:41:43 UTC
Comment on attachment 6491 [details]
git-am fix for 3.5.next

Yep, this fixes it!
Comment 11 Jeremy Allison 2011-05-27 16:57:49 UTC
Re-assigning to Karolin for inclusion in 3.5.x and 3.6.0.

Jeremy.
Comment 12 Karolin Seeger 2011-05-29 17:57:57 UTC
Pushed to v3-5-test and v3-6-test.
Closing out bug report.

Thanks!