LCOV - code coverage report
Current view: top level - source4/libcli/smb2 - signing.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 39 60 65.0 %
Date: 2024-04-21 15:09:00 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    SMB2 Signing Code
       5             : 
       6             :    Copyright (C) Andrew Tridgell <tridge@samba.org> 2008
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "libcli/raw/libcliraw.h"
      24             : #include "libcli/smb2/smb2.h"
      25             : #include "libcli/smb2/smb2_calls.h"
      26             : 
      27             : #include <gnutls/gnutls.h>
      28             : #include <gnutls/crypto.h>
      29             : #include "lib/crypto/gnutls_helpers.h"
      30             : 
      31             : /*
      32             :   sign an outgoing message
      33             :  */
      34      411669 : NTSTATUS smb2_sign_message(struct smb2_request_buffer *buf, DATA_BLOB session_key)
      35      411669 : {
      36      411669 :         uint8_t digest[gnutls_hmac_get_len(GNUTLS_MAC_SHA256)];
      37           0 :         uint64_t session_id;
      38           0 :         size_t hdr_offset;
      39           0 :         int rc;
      40             : 
      41      411669 :         if (buf->size < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) {
      42             :                 /* can't sign non-SMB2 messages */
      43           0 :                 return NT_STATUS_OK;
      44             :         }
      45             : 
      46      411669 :         hdr_offset = buf->hdr - buf->buffer;
      47             : 
      48      411669 :         session_id = BVAL(buf->hdr, SMB2_HDR_SESSION_ID);
      49      411669 :         if (session_id == 0) {
      50             :                 /* we don't sign messages with a zero session_id. See
      51             :                    MS-SMB2 3.2.4.1.1 */
      52           0 :                 return NT_STATUS_OK;
      53             :         }
      54             : 
      55      411669 :         if (session_key.length == 0) {
      56           0 :                 DEBUG(2,("Wrong session key length %u for SMB2 signing\n",
      57             :                          (unsigned)session_key.length));
      58           0 :                 return NT_STATUS_ACCESS_DENIED;
      59             :         }
      60             : 
      61      411669 :         memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16);
      62             : 
      63      411669 :         SIVAL(buf->hdr, SMB2_HDR_FLAGS, IVAL(buf->hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
      64             : 
      65      411669 :         rc = gnutls_hmac_fast(GNUTLS_MAC_SHA256,
      66      411669 :                               session_key.data,
      67      411669 :                               MIN(session_key.length, 16),
      68      411669 :                               buf->hdr,
      69      411669 :                               buf->size - hdr_offset,
      70             :                               digest);
      71      411669 :         if (rc < 0) {
      72           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
      73             :         }
      74             : 
      75      411669 :         DEBUG(5,("signed SMB2 message of size %u\n", (unsigned)buf->size - NBT_HDR_SIZE));
      76             : 
      77      411669 :         memcpy(buf->hdr + SMB2_HDR_SIGNATURE, digest, 16);
      78             : 
      79      411669 :         return NT_STATUS_OK;
      80             : }
      81             : 
      82             : /*
      83             :   check an incoming signature
      84             :  */
      85      410115 : NTSTATUS smb2_check_signature(struct smb2_request_buffer *buf, DATA_BLOB session_key)
      86      410115 : {
      87           0 :         uint64_t session_id;
      88      820230 :         uint8_t digest[gnutls_hmac_get_len(GNUTLS_MAC_SHA256)];
      89           0 :         uint8_t sig[16];
      90           0 :         size_t hdr_offset;
      91           0 :         int rc;
      92             : 
      93      410115 :         if (buf->size < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) {
      94             :                 /* can't check non-SMB2 messages */
      95           0 :                 return NT_STATUS_OK;
      96             :         }
      97             : 
      98      410115 :         hdr_offset = buf->hdr - buf->buffer;
      99             : 
     100      410115 :         session_id = BVAL(buf->hdr, SMB2_HDR_SESSION_ID);
     101      410115 :         if (session_id == 0) {
     102             :                 /* don't sign messages with a zero session_id. See
     103             :                    MS-SMB2 3.2.4.1.1 */
     104           0 :                 return NT_STATUS_OK;
     105             :         }
     106             : 
     107      410115 :         if (session_key.length == 0) {
     108             :                 /* we don't have the session key yet */
     109           0 :                 return NT_STATUS_OK;
     110             :         }
     111             : 
     112      410115 :         memcpy(sig, buf->hdr+SMB2_HDR_SIGNATURE, 16);
     113             : 
     114      410115 :         memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16);
     115             : 
     116      410115 :         rc = gnutls_hmac_fast(GNUTLS_MAC_SHA256,
     117      410115 :                               session_key.data,
     118      410115 :                               MIN(session_key.length, 16),
     119      410115 :                               buf->hdr,
     120      410115 :                               buf->size - hdr_offset,
     121             :                               digest);
     122      410115 :         if (rc < 0) {
     123           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     124             :         }
     125             : 
     126      410115 :         memcpy(buf->hdr + SMB2_HDR_SIGNATURE, digest, 16);
     127             : 
     128      410115 :         if (!mem_equal_const_time(digest, sig, 16)) {
     129           0 :                 DEBUG(0,("Bad SMB2 signature for message of size %u\n",
     130             :                          (unsigned)buf->size-NBT_HDR_SIZE));
     131           0 :                 dump_data(0, sig, 16);
     132           0 :                 dump_data(0, digest, 16);
     133           0 :                 ZERO_ARRAY(digest);
     134           0 :                 return NT_STATUS_ACCESS_DENIED;
     135             :         }
     136      410115 :         ZERO_ARRAY(digest);
     137             : 
     138      410115 :         return NT_STATUS_OK;
     139             : }

Generated by: LCOV version 1.14