LCOV - code coverage report
Current view: top level - source4/libcli/raw - smb_signing.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 101 134 75.4 %
Date: 2024-04-21 15:09:00 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB Signing Code
       4             :    Copyright (C) Jeremy Allison 2002.
       5             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
       6             :    Copyright (C) James J Myers <myersjj@samba.org> 2003
       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/raw/raw_proto.h"
      25             : #include "../lib/crypto/crypto.h"
      26             : 
      27             : #include <gnutls/gnutls.h>
      28             : #include <gnutls/crypto.h>
      29             : 
      30             : /***********************************************************
      31             :  SMB signing - Common code before we set a new signing implementation
      32             : ************************************************************/
      33         962 : bool set_smb_signing_common(struct smb_signing_context *sign_info)
      34             : {
      35         962 :         if (sign_info->doing_signing) {
      36          30 :                 DEBUG(5, ("SMB Signing already in progress, so we don't start it again\n"));
      37          30 :                 return false;
      38             :         }
      39             : 
      40         932 :         if (!sign_info->allow_smb_signing) {
      41           2 :                 DEBUG(5, ("SMB Signing has been locally disabled\n"));
      42           2 :                 return false;
      43             :         }
      44             : 
      45         930 :         return true;
      46             : }
      47             : 
      48      419841 : void mark_packet_signed(struct smb_request_buffer *out)
      49             : {
      50           0 :         uint16_t flags2;
      51      419841 :         flags2 = SVAL(out->hdr, HDR_FLG2);
      52      419841 :         flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
      53      419841 :         SSVAL(out->hdr, HDR_FLG2, flags2);
      54      419841 : }
      55             : 
      56      419618 : bool signing_good(struct smb_signing_context *sign_info,
      57             :                          unsigned int seq, bool good)
      58             : {
      59      419618 :         if (good) {
      60      419522 :                 if (!sign_info->doing_signing) {
      61         834 :                         DEBUG(5, ("Seen valid packet, so turning signing on\n"));
      62         834 :                         sign_info->doing_signing = true;
      63             :                 }
      64      419522 :                 if (!sign_info->seen_valid) {
      65         834 :                         DEBUG(5, ("Seen valid packet, so marking signing as 'seen valid'\n"));
      66         834 :                         sign_info->seen_valid = true;
      67             :                 }
      68             :         } else {
      69          96 :                 if (!sign_info->seen_valid) {
      70             :                         /* If we have never seen a good packet, just turn it off */
      71          96 :                         DEBUG(5, ("signing_good: signing negotiated but not required and peer\n"
      72             :                                   "isn't sending correct signatures. Turning off.\n"));
      73          96 :                         smbcli_set_signing_off(sign_info);
      74          96 :                         return true;
      75             :                 } else {
      76             :                         /* bad packet after signing started - fail and disconnect. */
      77           0 :                         DEBUG(0, ("signing_good: BAD SIG: seq %u\n", seq));
      78           0 :                         return false;
      79             :                 }
      80             :         }
      81      419522 :         return true;
      82             : }
      83             : 
      84      419841 : void sign_outgoing_message(struct smb_request_buffer *out, DATA_BLOB *mac_key, unsigned int seq_num)
      85             : {
      86           0 :         uint8_t calc_md5_mac[16];
      87      419841 :         gnutls_hash_hd_t hash_hnd = NULL;
      88           0 :         int rc;
      89             : 
      90             :         /*
      91             :          * Firstly put the sequence number into the first 4 bytes.
      92             :          * and zero out the next 4 bytes.
      93             :          */
      94      419841 :         SIVAL(out->hdr, HDR_SS_FIELD, seq_num);
      95      419841 :         SIVAL(out->hdr, HDR_SS_FIELD + 4, 0);
      96             : 
      97             :         /* mark the packet as signed - BEFORE we sign it...*/
      98      419841 :         mark_packet_signed(out);
      99             : 
     100             :         /* Calculate the 16 byte MAC and place first 8 bytes into the field. */
     101      419841 :         rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
     102      419841 :         if (rc < 0) {
     103           0 :                 return;
     104             :         }
     105             : 
     106      419841 :         rc = gnutls_hash(hash_hnd, mac_key->data, mac_key->length);
     107      419841 :         if (rc < 0) {
     108           0 :                 gnutls_hash_deinit(hash_hnd, NULL);
     109           0 :                 return;
     110             :         }
     111      419841 :         rc = gnutls_hash(hash_hnd,
     112      419841 :                          out->buffer + NBT_HDR_SIZE,
     113      419841 :                          out->size - NBT_HDR_SIZE);
     114      419841 :         if (rc < 0) {
     115           0 :                 gnutls_hash_deinit(hash_hnd, NULL);
     116           0 :                 return;
     117             :         }
     118      419841 :         gnutls_hash_deinit(hash_hnd, calc_md5_mac);
     119             : 
     120      419841 :         memcpy(&out->hdr[HDR_SS_FIELD], calc_md5_mac, 8);
     121             : 
     122      419841 :         DEBUG(5, ("sign_outgoing_message: SENT SIG (seq: %d): sent SMB signature of\n",
     123             :                   seq_num));
     124      419841 :         dump_data(5, calc_md5_mac, 8);
     125      419841 :         ZERO_ARRAY(calc_md5_mac);
     126             : /*      req->out.hdr[HDR_SS_FIELD+2]=0;
     127             :         Uncomment this to test if the remote server actually verifies signitures...*/
     128             : }
     129             : 
     130      419618 : bool check_signed_incoming_message(struct smb_request_buffer *in, DATA_BLOB *mac_key, unsigned int seq_num)
     131             : {
     132      419618 :         bool ok = false;
     133           0 :         uint8_t calc_md5_mac[16];
     134           0 :         uint8_t *server_sent_mac;
     135           0 :         uint8_t sequence_buf[8];
     136           0 :         gnutls_hash_hd_t hash_hnd;
     137      419618 :         const size_t offset_end_of_sig = (HDR_SS_FIELD + 8);
     138           0 :         int rc;
     139           0 :         int i;
     140      419618 :         const int sign_range = 0;
     141             : 
     142             :         /* room enough for the signature? */
     143      419618 :         if (in->size < NBT_HDR_SIZE + HDR_SS_FIELD + 8) {
     144           0 :                 return false;
     145             :         }
     146             : 
     147      419618 :         if (!mac_key->length) {
     148             :                 /* NO key yet */
     149           0 :                 return false;
     150             :         }
     151             : 
     152             :         /* its quite bogus to be guessing sequence numbers, but very useful
     153             :            when debugging signing implementations */
     154      419714 :         for (i = 0-sign_range; i <= 0+sign_range; i++) {
     155             :                 /*
     156             :                  * Firstly put the sequence number into the first 4 bytes.
     157             :                  * and zero out the next 4 bytes.
     158             :                  */
     159      419618 :                 SIVAL(sequence_buf, 0, seq_num + i);
     160      419618 :                 SIVAL(sequence_buf, 4, 0);
     161             : 
     162             :                 /* get a copy of the server-sent mac */
     163      419618 :                 server_sent_mac = &in->hdr[HDR_SS_FIELD];
     164             : 
     165             :                 /* Calculate the 16 byte MAC and place first 8 bytes into the field. */
     166      419618 :                 rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
     167      419618 :                 if (rc < 0) {
     168           0 :                         ok = false;
     169           0 :                         goto out;
     170             :                 }
     171             : 
     172      419618 :                 rc = gnutls_hash(hash_hnd, mac_key->data, mac_key->length);
     173      419618 :                 if (rc < 0) {
     174           0 :                         gnutls_hash_deinit(hash_hnd, NULL);
     175           0 :                         ok = false;
     176           0 :                         goto out;
     177             :                 }
     178      419618 :                 rc = gnutls_hash(hash_hnd, in->hdr, HDR_SS_FIELD);
     179      419618 :                 if (rc < 0) {
     180           0 :                         gnutls_hash_deinit(hash_hnd, NULL);
     181           0 :                         ok = false;
     182           0 :                         goto out;
     183             :                 }
     184      419618 :                 rc = gnutls_hash(hash_hnd, sequence_buf, sizeof(sequence_buf));
     185      419618 :                 if (rc < 0) {
     186           0 :                         gnutls_hash_deinit(hash_hnd, NULL);
     187           0 :                         ok = false;
     188           0 :                         goto out;
     189             :                 }
     190      419618 :                 rc = gnutls_hash(hash_hnd,
     191      419618 :                                  in->hdr + offset_end_of_sig,
     192      419618 :                                  in->size - NBT_HDR_SIZE - (offset_end_of_sig));
     193      419618 :                 if (rc < 0) {
     194           0 :                         gnutls_hash_deinit(hash_hnd, NULL);
     195           0 :                         ok = false;
     196           0 :                         goto out;
     197             :                 }
     198             : 
     199      419618 :                 gnutls_hash_deinit(hash_hnd, calc_md5_mac);
     200             : 
     201      419618 :                 ok = mem_equal_const_time(server_sent_mac, calc_md5_mac, 8);
     202             : 
     203      419618 :                 if (i == 0) {
     204      419618 :                         if (!ok) {
     205          96 :                                 DEBUG(5, ("check_signed_incoming_message: BAD SIG (seq: %d): wanted SMB signature of\n", seq_num + i));
     206          96 :                                 dump_data(5, calc_md5_mac, 8);
     207             : 
     208          96 :                                 DEBUG(5, ("check_signed_incoming_message: BAD SIG (seq: %d): got SMB signature of\n", seq_num + i));
     209          96 :                                 dump_data(5, server_sent_mac, 8);
     210             :                         } else {
     211      419522 :                                 DEBUG(15, ("check_signed_incoming_message: GOOD SIG (seq: %d): got SMB signature of\n", seq_num + i));
     212      419522 :                                 dump_data(5, server_sent_mac, 8);
     213             :                         }
     214             :                 }
     215      419618 :                 ZERO_ARRAY(calc_md5_mac);
     216             : 
     217      419618 :                 if (ok) break;
     218             :         }
     219             : 
     220      419618 :         if (ok && i != 0) {
     221           0 :                 DEBUG(0,("SIGNING OFFSET %d (should be %d)\n", i, seq_num));
     222             :         }
     223             : 
     224      419618 : out:
     225      419618 :         return ok;
     226             : }
     227             : 
     228             : /**
     229             :  SMB signing - NULL implementation
     230             : 
     231             :  @note Used as an initialisation only - it will not correctly
     232             :        shut down a real signing mechanism
     233             : */
     234        2261 : bool smbcli_set_signing_off(struct smb_signing_context *sign_info)
     235             : {
     236        2261 :         DEBUG(5, ("Shutdown SMB signing\n"));
     237        2261 :         sign_info->doing_signing = false;
     238        2261 :         data_blob_free(&sign_info->mac_key);
     239        2261 :         sign_info->signing_state = SMB_SIGNING_ENGINE_OFF;
     240        2261 :         return true;
     241             : }
     242             : 
     243             : /***********************************************************
     244             :  SMB signing - Simple implementation - setup the MAC key.
     245             : ************************************************************/
     246         930 : bool smbcli_simple_set_signing(TALLOC_CTX *mem_ctx,
     247             :                                struct smb_signing_context *sign_info,
     248             :                                const DATA_BLOB *user_session_key,
     249             :                                const DATA_BLOB *response)
     250             : {
     251         930 :         if (sign_info->mandatory_signing) {
     252         838 :                 DEBUG(5, ("Mandatory SMB signing enabled!\n"));
     253             :         }
     254             : 
     255         930 :         DEBUG(5, ("SMB signing enabled!\n"));
     256             : 
     257         930 :         if (response && response->length) {
     258           7 :                 sign_info->mac_key = data_blob_talloc(mem_ctx, NULL, response->length + user_session_key->length);
     259             :         } else {
     260         923 :                 sign_info->mac_key = data_blob_talloc(mem_ctx, NULL, user_session_key->length);
     261             :         }
     262             : 
     263         930 :         memcpy(&sign_info->mac_key.data[0], user_session_key->data, user_session_key->length);
     264             : 
     265         930 :         if (response && response->length) {
     266           7 :                 memcpy(&sign_info->mac_key.data[user_session_key->length],response->data, response->length);
     267             :         }
     268             : 
     269         930 :         dump_data_pw("Started Signing with key:\n", sign_info->mac_key.data, sign_info->mac_key.length);
     270             : 
     271         930 :         sign_info->signing_state = SMB_SIGNING_ENGINE_ON;
     272         930 :         sign_info->next_seq_num = 2;
     273             : 
     274         930 :         return true;
     275             : }

Generated by: LCOV version 1.14