LCOV - code coverage report
Current view: top level - source4/libcli/smb2 - signing.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 39 53 73.6 %
Date: 2021-09-23 10:06:22 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      397039 : NTSTATUS smb2_sign_message(struct smb2_request_buffer *buf, DATA_BLOB session_key)
      35      397039 : {
      36      397039 :         uint8_t digest[gnutls_hash_get_len(GNUTLS_MAC_SHA256)];
      37             :         uint64_t session_id;
      38             :         size_t hdr_offset;
      39             :         int rc;
      40             : 
      41      397039 :         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      397039 :         hdr_offset = buf->hdr - buf->buffer;
      47             : 
      48      397039 :         session_id = BVAL(buf->hdr, SMB2_HDR_SESSION_ID);
      49      397039 :         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      397039 :         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      397039 :         memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16);
      62             : 
      63      397039 :         SIVAL(buf->hdr, SMB2_HDR_FLAGS, IVAL(buf->hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
      64             : 
      65     1551346 :         rc = gnutls_hmac_fast(GNUTLS_MAC_SHA256,
      66      397039 :                               session_key.data,
      67      397039 :                               MIN(session_key.length, 16),
      68      397039 :                               buf->hdr,
      69      397039 :                               buf->size - hdr_offset,
      70             :                               digest);
      71      397039 :         if (rc < 0) {
      72           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
      73             :         }
      74             : 
      75      397039 :         DEBUG(5,("signed SMB2 message of size %u\n", (unsigned)buf->size - NBT_HDR_SIZE));
      76             : 
      77      397039 :         memcpy(buf->hdr + SMB2_HDR_SIGNATURE, digest, 16);
      78             : 
      79      397039 :         return NT_STATUS_OK;    
      80             : }
      81             : 
      82             : /*
      83             :   check an incoming signature
      84             :  */
      85      395398 : NTSTATUS smb2_check_signature(struct smb2_request_buffer *buf, DATA_BLOB session_key)
      86      395398 : {
      87             :         uint64_t session_id;
      88     1174259 :         uint8_t digest[gnutls_hash_get_len(GNUTLS_MAC_SHA256)];
      89             :         uint8_t sig[16];
      90             :         size_t hdr_offset;
      91             :         int rc;
      92             : 
      93      395398 :         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      395398 :         hdr_offset = buf->hdr - buf->buffer;
      99             : 
     100      395398 :         session_id = BVAL(buf->hdr, SMB2_HDR_SESSION_ID);
     101      395398 :         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      395398 :         if (session_key.length == 0) {
     108             :                 /* we don't have the session key yet */
     109           0 :                 return NT_STATUS_OK;
     110             :         }
     111             : 
     112      395398 :         memcpy(sig, buf->hdr+SMB2_HDR_SIGNATURE, 16);
     113             : 
     114      395398 :         memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16);
     115             : 
     116     1545787 :         rc = gnutls_hmac_fast(GNUTLS_MAC_SHA256,
     117      395398 :                               session_key.data,
     118      395398 :                               MIN(session_key.length, 16),
     119      395398 :                               buf->hdr,
     120      395398 :                               buf->size - hdr_offset,
     121             :                               digest);
     122      395398 :         if (rc < 0) {
     123           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
     124             :         }
     125             : 
     126      395398 :         memcpy(buf->hdr + SMB2_HDR_SIGNATURE, digest, 16);
     127             : 
     128      395398 :         if (memcmp_const_time(digest, sig, 16) != 0) {
     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      778861 :         ZERO_ARRAY(digest);
     137             : 
     138      395398 :         return NT_STATUS_OK;    
     139             : }

Generated by: LCOV version 1.13