Kai Blin : secur32: Implement NTLM2 encryption.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Nov 9 13:57:20 CST 2006


Module: wine
Branch: master
Commit: d5c0acd0576f26b64186cbf3211e7924a5704851
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d5c0acd0576f26b64186cbf3211e7924a5704851

Author: Kai Blin <kai.blin at gmail.com>
Date:   Thu Nov  9 11:31:31 2006 +0100

secur32: Implement NTLM2 encryption.

---

 dlls/secur32/ntlm.c |  115 ++++++++++++++++++++-------------------------------
 1 files changed, 45 insertions(+), 70 deletions(-)

diff --git a/dlls/secur32/ntlm.c b/dlls/secur32/ntlm.c
index 1bee91b..257562b 100644
--- a/dlls/secur32/ntlm.c
+++ b/dlls/secur32/ntlm.c
@@ -1235,14 +1235,20 @@ static int ntlm_GetTokenBufferIndex(PSec
  *             ntlm_CreateSignature
  * As both MakeSignature and VerifySignature need this, but different keys
  * are needed for NTLMv2, the logic goes into a helper function.
+ * To ensure maximal reusability, we can specify the direction as NTLM_SEND for
+ * signing/encrypting and NTLM_RECV for verfying/decrypting. When encrypting,
+ * the signature is encrypted after the message was encrypted, so
+ * CreateSignature shouldn't do it. In this case, encrypt_sig can be set to
+ * false.
  */
 static SECURITY_STATUS ntlm_CreateSignature(PNegoHelper helper, PSecBufferDesc pMessage,
-        int token_idx, SignDirection direction)
+        int token_idx, SignDirection direction, BOOL encrypt_sig)
 {
     ULONG sign_version = 1;
     UINT i;
     PBYTE sig;
-    TRACE("%p, %p, %d, %d\n", helper, pMessage, token_idx, direction);
+    TRACE("%p, %p, %d, %d, %d\n", helper, pMessage, token_idx, direction,
+            encrypt_sig);
 
     sig = pMessage->pBuffers[token_idx].pvBuffer;
 
@@ -1253,11 +1259,10 @@ static SECURITY_STATUS ntlm_CreateSignat
         BYTE seq_no[4];
         HMAC_MD5_CTX hmac_md5_ctx;
 
-        TRACE("Encrypting NTLM2 style\n");
+        TRACE("Signing NTLM2 style\n");
 
         if(direction == NTLM_SEND)
         {
-            TRACE("Signing for sending\n");
             seq_no[0] = (helper->crypt.ntlm2.send_seq_no >>  0) & 0xff;
             seq_no[1] = (helper->crypt.ntlm2.send_seq_no >>  8) & 0xff;
             seq_no[2] = (helper->crypt.ntlm2.send_seq_no >> 16) & 0xff;
@@ -1265,9 +1270,7 @@ static SECURITY_STATUS ntlm_CreateSignat
 
             ++(helper->crypt.ntlm2.send_seq_no);
 
-            TRACE("HMACMD5Init...\n");
             HMACMD5Init(&hmac_md5_ctx, helper->crypt.ntlm2.send_sign_key, 16);
-            TRACE("Done\n");
         }
         else
         {
@@ -1281,8 +1284,6 @@ static SECURITY_STATUS ntlm_CreateSignat
             HMACMD5Init(&hmac_md5_ctx, helper->crypt.ntlm2.recv_sign_key, 16);
         }
 
-        TRACE("Starting the update loop\n");
-
         HMACMD5Update(&hmac_md5_ctx, seq_no, 4);
         for( i = 0; i < pMessage->cBuffers; ++i )
         {
@@ -1293,9 +1294,7 @@ static SECURITY_STATUS ntlm_CreateSignat
 
         HMACMD5Final(&hmac_md5_ctx, digest);
 
-        TRACE("After HMACMD5Final\n");
-
-        if(helper->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCHANGE)
+        if(encrypt_sig && helper->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCHANGE)
         {
             if(direction == NTLM_SEND)
                 SECUR32_arc4Process(helper->crypt.ntlm2.send_a4i, digest, 8);
@@ -1320,6 +1319,7 @@ static SECURITY_STATUS ntlm_CreateSignat
     if(helper->neg_flags & NTLMSSP_NEGOTIATE_SIGN)
     {
         ULONG crc = 0U;
+        TRACE("Signing NTLM1 style\n");
 
         for(i=0; i < pMessage->cBuffers; ++i)
         {
@@ -1346,7 +1346,8 @@ static SECURITY_STATUS ntlm_CreateSignat
 
         ++(helper->crypt.ntlm.seq_num);
 
-        SECUR32_arc4Process(helper->crypt.ntlm.a4i, sig+4, 12);
+        if(encrypt_sig)
+            SECUR32_arc4Process(helper->crypt.ntlm.a4i, sig+4, 12);
         return SEC_E_OK;
     }
 
@@ -1395,7 +1396,7 @@ static SECURITY_STATUS SEC_ENTRY ntlm_Ma
     helper = (PNegoHelper)phContext->dwLower;
     TRACE("Negotiated flags are: 0x%08lx\n", helper->neg_flags);
 
-    return ntlm_CreateSignature(helper, pMessage, token_idx, NTLM_SEND);
+    return ntlm_CreateSignature(helper, pMessage, token_idx, NTLM_SEND, TRUE);
 }
 
 /***********************************************************************
@@ -1454,7 +1455,7 @@ static SECURITY_STATUS SEC_ENTRY ntlm_Ve
         }
     }
 
-    if((ret = ntlm_CreateSignature(helper, &local_desc, token_idx, NTLM_RECV)) != SEC_E_OK)
+    if((ret = ntlm_CreateSignature(helper, &local_desc, token_idx, NTLM_RECV, TRUE)) != SEC_E_OK)
         return ret;
 
     if(memcmp(((PBYTE)local_buff[token_idx].pvBuffer) + 8,
@@ -1498,8 +1499,7 @@ static SECURITY_STATUS SEC_ENTRY ntlm_En
         ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
 {
     PNegoHelper helper;
-    UINT i;
-    int token_idx = -1;
+    int token_idx;
 
     TRACE("(%p %d %p %d)\n", phContext, fQOP, pMessage, MessageSeqNo);
 
@@ -1515,16 +1515,7 @@ static SECURITY_STATUS SEC_ENTRY ntlm_En
     if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
         return SEC_E_INVALID_TOKEN;
 
-    for(i=0; i < pMessage->cBuffers; ++i)
-    {
-        if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
-        {
-            token_idx = i;
-            break;
-        }
-    }
-
-    if(token_idx == -1)
+    if((token_idx = ntlm_GetTokenBufferIndex(pMessage)) == -1)
         return SEC_E_INVALID_TOKEN;
 
     if(pMessage->pBuffers[token_idx].cbBuffer < 16)
@@ -1532,39 +1523,34 @@ static SECURITY_STATUS SEC_ENTRY ntlm_En
 
     helper = (PNegoHelper) phContext->dwLower;
 
-    if(helper->neg_flags & NTLMSSP_NEGOTIATE_NTLM2)
-    {
-        FIXME("Can't handle NTLMv2 encryption yet, aborting\n");
-        return SEC_E_UNSUPPORTED_FUNCTION;
+    if(helper->neg_flags & NTLMSSP_NEGOTIATE_NTLM2 && 
+            helper->neg_flags & NTLMSSP_NEGOTIATE_SEAL)
+    { 
+        ntlm_CreateSignature(helper, pMessage, token_idx, NTLM_SEND, FALSE);
+        SECUR32_arc4Process(helper->crypt.ntlm2.send_a4i,
+                (BYTE *)pMessage->pBuffers[1].pvBuffer,
+                pMessage->pBuffers[1].cbBuffer);
+
+        if(helper->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCHANGE)
+            SECUR32_arc4Process(helper->crypt.ntlm2.send_a4i,
+                    ((BYTE *)pMessage->pBuffers[token_idx].pvBuffer)+4, 8);
+
+
+        return SEC_E_OK;
     }
     else
     {
-        PBYTE sig = pMessage->pBuffers[token_idx].pvBuffer;
-        ULONG crc = 0U;
-        ULONG sign_version = 1l;
+        PBYTE sig;
+        ULONG save_flags;
 
-        for(i=0; i < pMessage->cBuffers; ++i)
-        {
-            if(pMessage->pBuffers[i].BufferType & SECBUFFER_DATA)
-            {
-                crc = ComputeCrc32(pMessage->pBuffers[i].pvBuffer,
-                    pMessage->pBuffers[i].cbBuffer, crc);
-            }
-        }
+        /* EncryptMessage always produces real signatures, so make sure
+         * NTLMSSP_NEGOTIATE_SIGN is set*/
+        save_flags = helper->neg_flags;
+        helper->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
+        ntlm_CreateSignature(helper, pMessage, token_idx, NTLM_SEND, FALSE);
+        helper->neg_flags = save_flags;
 
-        sig[ 0] = (sign_version >>  0) & 0xff;
-        sig[ 1] = (sign_version >>  8) & 0xff;
-        sig[ 2] = (sign_version >> 16) & 0xff;
-        sig[ 3] = (sign_version >> 24) & 0xff;
-        memset(sig+4, 0, 4);
-        sig[ 8] = (crc >>  0) & 0xff;
-        sig[ 9] = (crc >>  8) & 0xff;
-        sig[10] = (crc >> 16) & 0xff;
-        sig[11] = (crc >> 24) & 0xff;
-        sig[12] = (helper->crypt.ntlm.seq_num >>  0) & 0xff;
-        sig[13] = (helper->crypt.ntlm.seq_num >>  8) & 0xff;
-        sig[14] = (helper->crypt.ntlm.seq_num >> 16) & 0xff;
-        sig[15] = (helper->crypt.ntlm.seq_num >> 24) & 0xff;
+        sig = pMessage->pBuffers[token_idx].pvBuffer;
 
         SECUR32_arc4Process(helper->crypt.ntlm.a4i, pMessage->pBuffers[1].pvBuffer,
                 pMessage->pBuffers[1].cbBuffer);
@@ -1573,8 +1559,6 @@ static SECURITY_STATUS SEC_ENTRY ntlm_En
         if(helper->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN || helper->neg_flags == 0)
             memset(sig+4, 0, 4);
 
-        ++(helper->crypt.ntlm.seq_num);
-
     }
 
     return SEC_E_OK;
@@ -1589,8 +1573,7 @@ static SECURITY_STATUS SEC_ENTRY ntlm_De
     SECURITY_STATUS ret;
     ULONG ntlmssp_flags_save;
     PNegoHelper helper;
-    UINT i;
-    int token_idx = -1;
+    int token_idx;
     TRACE("(%p %p %d %p)\n", phContext, pMessage, MessageSeqNo, pfQOP);
 
     if(!phContext)
@@ -1602,15 +1585,7 @@ static SECURITY_STATUS SEC_ENTRY ntlm_De
     if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
         return SEC_E_INVALID_TOKEN;
 
-    for(i=0; i < pMessage->cBuffers; ++i)
-    {
-        if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
-        {
-            token_idx = i;
-            break;
-        }
-    }
-    if(token_idx == -1)
+    if((token_idx = ntlm_GetTokenBufferIndex(pMessage)) == -1)
         return SEC_E_INVALID_TOKEN;
 
     if(pMessage->pBuffers[token_idx].cbBuffer < 16)
@@ -1618,10 +1593,10 @@ static SECURITY_STATUS SEC_ENTRY ntlm_De
 
     helper = (PNegoHelper) phContext->dwLower;
 
-    if(helper->neg_flags & NTLMSSP_NEGOTIATE_NTLM2)
+    if(helper->neg_flags & NTLMSSP_NEGOTIATE_NTLM2 && helper->neg_flags & NTLMSSP_NEGOTIATE_SEAL)
     {
-        FIXME("Can't handle NTLMv2 encryption yet, aborting\n");
-        return SEC_E_UNSUPPORTED_FUNCTION;
+        SECUR32_arc4Process(helper->crypt.ntlm2.recv_a4i,
+                pMessage->pBuffers[1].pvBuffer, pMessage->pBuffers[1].cbBuffer);
     }
     else
     {




More information about the wine-cvs mailing list