LCOV - code coverage report
Current view: top level - libcli/smb - smb_seal.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 51 79 64.6 %
Date: 2024-04-21 15:09:00 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB Transport encryption (sealing) code.
       4             :    Copyright (C) Jeremy Allison 2007.
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "smb_common.h"
      22             : #ifdef HAVE_KRB5
      23             : #include "lib/krb5_wrap/krb5_samba.h"
      24             : #endif
      25             : #include "auth/gensec/gensec.h"
      26             : #include "libcli/smb/smb_seal.h"
      27             : 
      28             : #undef malloc
      29             : 
      30             : /******************************************************************************
      31             :  Pull out the encryption context for this packet. 0 means global context.
      32             : ******************************************************************************/
      33             : 
      34      521299 : NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16_t *p_enc_ctx_num)
      35             : {
      36      521299 :         if (smb_len_nbt(buf) < 8) {
      37           0 :                 return NT_STATUS_INVALID_BUFFER_SIZE;
      38             :         }
      39             : 
      40      521299 :         if (buf[4] == 0xFF) {
      41      521299 :                 if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
      42             :                         /* Not an encrypted buffer. */
      43           0 :                         return NT_STATUS_NOT_FOUND;
      44             :                 }
      45      521299 :                 if (buf[5] == 'E') {
      46      521299 :                         *p_enc_ctx_num = SVAL(buf,6);
      47      521299 :                         return NT_STATUS_OK;
      48             :                 }
      49             :         }
      50           0 :         return NT_STATUS_INVALID_NETWORK_RESPONSE;
      51             : }
      52             : 
      53             : /*******************************************************************
      54             :  Set the length and marker of an encrypted smb packet.
      55             : ********************************************************************/
      56             : 
      57      335416 : static void smb_set_enclen(char *buf,int len,uint16_t enc_ctx_num)
      58             : {
      59      335416 :         _smb_setlen_tcp(buf,len);
      60             : 
      61      335416 :         SCVAL(buf,4,0xFF);
      62      335416 :         SCVAL(buf,5,'E');
      63      335416 :         SSVAL(buf,6,enc_ctx_num);
      64      335416 : }
      65             : 
      66             : /******************************************************************************
      67             :  Generic code for client and server.
      68             :  Is encryption turned on ?
      69             : ******************************************************************************/
      70             : 
      71     2749386 : bool common_encryption_on(struct smb_trans_enc_state *es)
      72             : {
      73     2749386 :         return ((es != NULL) && es->enc_on);
      74             : }
      75             : 
      76             : /******************************************************************************
      77             :  Generic code for client and server.
      78             :  GENSEC decrypt an incoming buffer.
      79             : ******************************************************************************/
      80             : 
      81      335416 : static NTSTATUS common_gensec_decrypt_buffer(struct gensec_security *gensec,
      82             :                                              char *buf)
      83             : {
      84           0 :         NTSTATUS status;
      85      335416 :         size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
      86           0 :         DATA_BLOB in_buf, out_buf;
      87           0 :         TALLOC_CTX *frame;
      88             : 
      89      335416 :         if (buf_len < 8) {
      90           0 :                 return NT_STATUS_BUFFER_TOO_SMALL;
      91             :         }
      92             : 
      93      335416 :         frame = talloc_stackframe();
      94             : 
      95      335416 :         in_buf = data_blob_const(buf + 8, buf_len - 8);
      96             : 
      97      335416 :         status = gensec_unwrap(gensec, frame, &in_buf, &out_buf);
      98             : 
      99      335416 :         if (!NT_STATUS_IS_OK(status)) {
     100           0 :                 DEBUG(0,("common_gensec_decrypt_buffer: gensec_unwrap failed. Error %s\n",
     101             :                          nt_errstr(status)));
     102           0 :                 TALLOC_FREE(frame);
     103           0 :                 return status;
     104             :         }
     105             : 
     106      335416 :         if (out_buf.length > in_buf.length) {
     107           0 :                 DEBUG(0,("common_gensec_decrypt_buffer: gensec_unwrap size (%u) too large (%u) !\n",
     108             :                         (unsigned int)out_buf.length,
     109             :                         (unsigned int)in_buf.length ));
     110           0 :                 TALLOC_FREE(frame);
     111           0 :                 return NT_STATUS_INVALID_PARAMETER;
     112             :         }
     113             : 
     114      335416 :         memcpy(buf + 8, out_buf.data, out_buf.length);
     115             : 
     116             :         /* Reset the length and overwrite the header. */
     117      335416 :         smb_setlen_nbt(buf, out_buf.length + 4);
     118             : 
     119      335416 :         TALLOC_FREE(frame);
     120             : 
     121      335416 :         return NT_STATUS_OK;
     122             : }
     123             : 
     124             : /******************************************************************************
     125             :  Generic code for client and server.
     126             :  NTLM encrypt an outgoing buffer. Return the encrypted pointer in ppbuf_out.
     127             : ******************************************************************************/
     128             : 
     129      335416 : static NTSTATUS common_gensec_encrypt_buffer(struct gensec_security *gensec,
     130             :                                       uint16_t enc_ctx_num,
     131             :                                       char *buf,
     132             :                                       char **ppbuf_out)
     133             : {
     134           0 :         NTSTATUS status;
     135           0 :         DATA_BLOB in_buf, out_buf;
     136      335416 :         size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
     137           0 :         TALLOC_CTX *frame;
     138             : 
     139      335416 :         *ppbuf_out = NULL;
     140             : 
     141      335416 :         if (buf_len < 8) {
     142           0 :                 return NT_STATUS_BUFFER_TOO_SMALL;
     143             :         }
     144      335416 :         in_buf = data_blob_const(buf + 8, buf_len - 8);
     145             : 
     146      335416 :         frame = talloc_stackframe();
     147             : 
     148      335416 :         status = gensec_wrap(gensec, frame, &in_buf, &out_buf);
     149      335416 :         if (!NT_STATUS_IS_OK(status)) {
     150           0 :                 DEBUG(0,("common_gensec_encrypt_buffer: gensec_wrap failed. Error %s\n",
     151             :                          nt_errstr(status)));
     152           0 :                 TALLOC_FREE(frame);
     153           0 :                 return status;
     154             :         }
     155             : 
     156      335416 :         *ppbuf_out = (char *)malloc(out_buf.length + 8); /* We know this can't wrap. */
     157      335416 :         if (!*ppbuf_out) {
     158           0 :                 TALLOC_FREE(frame);
     159           0 :                 return NT_STATUS_NO_MEMORY;
     160             :         }
     161             : 
     162      335416 :         memcpy(*ppbuf_out+8, out_buf.data, out_buf.length);
     163      335416 :         smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);
     164             : 
     165      335416 :         TALLOC_FREE(frame);
     166             : 
     167      335416 :         return NT_STATUS_OK;
     168             : }
     169             : 
     170             : /******************************************************************************
     171             :  Generic code for client and server.
     172             :  Encrypt an outgoing buffer. Return the alloced encrypted pointer in buf_out.
     173             : ******************************************************************************/
     174             : 
     175      335416 : NTSTATUS common_encrypt_buffer(struct smb_trans_enc_state *es, char *buffer, char **buf_out)
     176             : {
     177      335416 :         if (!common_encryption_on(es)) {
     178             :                 /* Not encrypting. */
     179           0 :                 *buf_out = buffer;
     180           0 :                 return NT_STATUS_OK;
     181             :         }
     182             : 
     183      335416 :         return common_gensec_encrypt_buffer(es->gensec_security, es->enc_ctx_num, buffer, buf_out);
     184             : }
     185             : 
     186             : /******************************************************************************
     187             :  Generic code for client and server.
     188             :  Decrypt an incoming SMB buffer. Replaces the data within it.
     189             :  New data must be less than or equal to the current length.
     190             : ******************************************************************************/
     191             : 
     192      335416 : NTSTATUS common_decrypt_buffer(struct smb_trans_enc_state *es, char *buf)
     193             : {
     194      335416 :         if (!common_encryption_on(es)) {
     195             :                 /* Not decrypting. */
     196           0 :                 return NT_STATUS_OK;
     197             :         }
     198             : 
     199      335416 :         return common_gensec_decrypt_buffer(es->gensec_security, buf);
     200             : }
     201             : 
     202             : /******************************************************************************
     203             :  Free an encryption-allocated buffer.
     204             : ******************************************************************************/
     205             : 
     206      185883 : void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
     207             : {
     208           0 :         uint16_t enc_ctx_num;
     209             : 
     210      185883 :         if (!common_encryption_on(es)) {
     211           0 :                 return;
     212             :         }
     213             : 
     214      185883 :         if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,
     215             :                         &enc_ctx_num))) {
     216           0 :                 return;
     217             :         }
     218             : 
     219      185883 :         SAFE_FREE(buf);
     220             : }

Generated by: LCOV version 1.14