[PATCH] Reuse of nonces patch breaks SMB3.0 connections without encryption.

Jeremy Allison jra at samba.org
Tue Jun 16 16:58:34 MDT 2015

The commit :

commit 461c69bd7c52c8b980cf56be2abf9ce7accb6048
Author: Simo Sorce <idra at samba.org>
Date:   Wed May 20 14:01:44 2015 +0200

    s3:smb2_server: In CCM and GCM mode we can't reuse nonces
    Reuse of nonces with AES-CCM and AES-GCM leads to catastrophic failure,
    so make sure the server drops the connection if that ever happens.
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=11300
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    Signed-off-by: Simo Sorce <simo at redhat.com>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>

that went into master breaks non-encrypted SMB3.0
connections. The problem is the hunk added here:

@@ -349,8 +353,31 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
                                    d->context.data, d->context.length,
-               generate_random_buffer((uint8_t *)&x->nonce_high, sizeof(x->nonce_high));
-               x->nonce_low = 1;
+               /*
+                * CCM and GCM algorithms must never have their
+                * nonce wrap, or the security of the whole
+                * communication and the keys is destroyed.
+                * We must drop the connection once we have
+                * transfered too much data.
+                *
+                * NOTE: We assume nonces greater than 8 bytes.
+                */
+               generate_random_buffer((uint8_t *)&x->nonce_high_random,
+                                      sizeof(x->nonce_high_random));
+               switch (xconn->smb2.server.cipher) {
+               case SMB2_ENCRYPTION_AES128_CCM:
+                       nonce_size = AES_CCM_128_NONCE_SIZE;
+                       break;
+               case SMB2_ENCRYPTION_AES128_GCM:
+                       nonce_size = AES_GCM_128_IV_SIZE;
+                       break;
+               default:
+                       ZERO_STRUCT(session_key);
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+               x->nonce_high_max = SMB2_NONCE_HIGH_MAX(nonce_size);
+               x->nonce_high = 0;
+               x->nonce_low = 0;

The previous code generated the nonce and did not
look at xconn->smb2.server.cipher, meaning in the
non-encrypted case where xconn->smb2.server.cipher == 0
the nonce was ignored.

Now if a client negotiates >= PROTOCOL_SMB2_24
but doesn't negotiate encryption (i.e. xconn->smb2.server.cipher == 0)
we run smack into the default case and return
sessionsetup fails.

The only place the nonces are actually used is
in smb2_get_new_nonce(), which is only used in
two places:

1). smbd_smb2_request_reply() when req->do_encryption == true.
2). smbd_smb2_send_break() when session->global->encryption_required == true
or tcon->global->encryption_required == true.

Now req->do_encryption is set to true if
a header of size SMB2_TF_HDR_SIZE is sent, so
this might get set at any time by a client
request, even if the client didn't negotiate

So I think the correct fix to protect all
code paths is in the case where xconn->smb2.server.cipher
is unknown (the default: case) is to set x->nonce_high_max = 0,
and then add a check inside smb2_get_new_nonce() to
x->nonce_high_max == 0.

Patch to do this attached. Please check.

FYI. This bug was found by Codenomicon at
the plugfest.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-smbd-Fix-clients-connecting-unencrypted-with-PROTOCO.patch
Type: text/x-diff
Size: 1754 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20150616/9dbe1ddc/attachment.patch>

More information about the samba-technical mailing list