LCOV - code coverage report
Current view: top level - libcli/smb - smb2_create_blob.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 96 112 85.7 %
Date: 2024-04-21 15:09:00 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    SMB2 Create Context Blob handling
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2005
       7             :    Copyright (C) Stefan Metzmacher 2008-2009
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "../libcli/smb/smb_common.h"
      25             : 
      26       13199 : static size_t smb2_create_blob_padding(uint32_t offset, size_t n)
      27             : {
      28       13199 :         if ((offset & (n-1)) == 0) return 0;
      29        8092 :         return n - (offset & (n-1));
      30             : }
      31             : 
      32             : /*
      33             :   parse a set of SMB2 create blobs
      34             : */
      35     1145047 : NTSTATUS smb2_create_blob_parse(TALLOC_CTX *mem_ctx, const DATA_BLOB buffer,
      36             :                                 struct smb2_create_blobs *blobs)
      37             : {
      38     1145047 :         const uint8_t *data = buffer.data;
      39     1145047 :         uint32_t remaining = buffer.length;
      40             : 
      41     1145900 :         while (remaining > 0) {
      42           0 :                 uint32_t next;
      43           0 :                 uint32_t name_offset, name_length;
      44           0 :                 uint32_t data_offset;
      45           0 :                 uint32_t data_length;
      46           0 :                 char *tag;
      47           0 :                 DATA_BLOB b;
      48           0 :                 NTSTATUS status;
      49             : 
      50       12474 :                 if (remaining < 16) {
      51           0 :                         return NT_STATUS_INVALID_PARAMETER;
      52             :                 }
      53       12474 :                 next        = IVAL(data, 0);
      54       12474 :                 name_offset = SVAL(data, 4);
      55       12474 :                 name_length = SVAL(data, 6);
      56             : #if 0
      57             :                 reserved    = SVAL(data, 8);
      58             : #endif
      59       12474 :                 data_offset = SVAL(data, 10);
      60       12474 :                 data_length = IVAL(data, 12);
      61             : 
      62       12474 :                 if ((next & 0x7) != 0 ||
      63       12474 :                     next > remaining ||
      64       12474 :                     name_offset != 16 ||
      65       12470 :                     name_length < 4 ||
      66       12470 :                     name_offset + name_length > remaining ||
      67       12470 :                     (data_offset & 0x7) != 0 ||
      68       12470 :                     (data_offset && (data_offset < name_offset + name_length)) ||
      69       12470 :                     (data_offset > remaining) ||
      70       12470 :                     (data_offset + (uint64_t)data_length > remaining)) {
      71           4 :                         return NT_STATUS_INVALID_PARAMETER;
      72             :                 }
      73             : 
      74       12470 :                 tag = talloc_strndup(mem_ctx, (const char *)data + name_offset, name_length);
      75       12470 :                 if (tag == NULL) {
      76           0 :                         return NT_STATUS_NO_MEMORY;
      77             :                 }
      78             : 
      79       12470 :                 b = data_blob_const(data+data_offset, data_length);
      80       12470 :                 status = smb2_create_blob_add(mem_ctx, blobs, tag, b);
      81       12470 :                 if (!NT_STATUS_IS_OK(status)) {
      82           0 :                         return status;
      83             :                 }
      84             : 
      85       12470 :                 talloc_free(tag);
      86             : 
      87       12470 :                 if (next == 0) break;
      88             : 
      89         853 :                 remaining -= next;
      90         853 :                 data += next;
      91             : 
      92         853 :                 if (remaining < 16) {
      93           0 :                         return NT_STATUS_INVALID_PARAMETER;
      94             :                 }
      95             :         }
      96             : 
      97     1145043 :         return NT_STATUS_OK;
      98             : }
      99             : 
     100             : 
     101             : /*
     102             :   add a blob to a smb2_create attribute blob
     103             : */
     104       12350 : static NTSTATUS smb2_create_blob_push_one(TALLOC_CTX *mem_ctx, DATA_BLOB *buffer,
     105             :                                           const struct smb2_create_blob *blob,
     106             :                                           bool last)
     107             : {
     108       12350 :         uint32_t ofs = buffer->length;
     109       12350 :         size_t tag_length = strlen(blob->tag);
     110       12350 :         size_t blob_offset = 0;
     111       12350 :         size_t blob_pad = 0;
     112       12350 :         size_t next_offset = 0;
     113       12350 :         size_t next_pad = 0;
     114           0 :         bool ok;
     115             : 
     116       12350 :         blob_offset = 0x10 + tag_length;
     117       12350 :         blob_pad = smb2_create_blob_padding(blob_offset, 8);
     118       12350 :         next_offset = blob_offset + blob_pad + blob->data.length;
     119       12350 :         if (!last) {
     120         849 :                 next_pad = smb2_create_blob_padding(next_offset, 8);
     121             :         }
     122             : 
     123       12350 :         ok = data_blob_realloc(mem_ctx, buffer,
     124       12350 :                                buffer->length + next_offset + next_pad);
     125       12350 :         if (!ok) {
     126           0 :                 return NT_STATUS_NO_MEMORY;
     127             :         }
     128             : 
     129       12350 :         if (last) {
     130       11501 :                 SIVAL(buffer->data, ofs+0x00, 0);
     131             :         } else {
     132         849 :                 SIVAL(buffer->data, ofs+0x00, next_offset + next_pad);
     133             :         }
     134       12350 :         SSVAL(buffer->data, ofs+0x04, 0x10); /* offset of tag */
     135       12350 :         SIVAL(buffer->data, ofs+0x06, tag_length); /* tag length */
     136       12350 :         SSVAL(buffer->data, ofs+0x0A, blob_offset + blob_pad); /* offset of data */
     137       12350 :         SIVAL(buffer->data, ofs+0x0C, blob->data.length);
     138       12350 :         memcpy(buffer->data+ofs+0x10, blob->tag, tag_length);
     139       12350 :         if (blob_pad > 0) {
     140        8054 :                 memset(buffer->data+ofs+blob_offset, 0, blob_pad);
     141        8054 :                 blob_offset += blob_pad;
     142             :         }
     143       12350 :         memcpy(buffer->data+ofs+blob_offset, blob->data.data, blob->data.length);
     144       12350 :         if (next_pad > 0) {
     145          38 :                 memset(buffer->data+ofs+next_offset, 0, next_pad);
     146             :         }
     147             : 
     148       12350 :         return NT_STATUS_OK;
     149             : }
     150             : 
     151             : 
     152             : /*
     153             :   create a buffer of a set of create blobs
     154             : */
     155     1189095 : NTSTATUS smb2_create_blob_push(TALLOC_CTX *mem_ctx, DATA_BLOB *buffer,
     156             :                                const struct smb2_create_blobs blobs)
     157             : {
     158        1156 :         uint32_t i;
     159        1156 :         NTSTATUS status;
     160             : 
     161     1189095 :         *buffer = (DATA_BLOB) { 0 };
     162     1201445 :         for (i=0; i < blobs.num_blobs; i++) {
     163       12350 :                 bool last = false;
     164           0 :                 const struct smb2_create_blob *c;
     165             : 
     166       12350 :                 if ((i + 1) == blobs.num_blobs) {
     167       11501 :                         last = true;
     168             :                 }
     169             : 
     170       12350 :                 c = &blobs.blobs[i];
     171       12350 :                 status = smb2_create_blob_push_one(mem_ctx, buffer, c, last);
     172       12350 :                 if (!NT_STATUS_IS_OK(status)) {
     173           0 :                         return status;
     174             :                 }
     175             :         }
     176     1189095 :         return NT_STATUS_OK;
     177             : }
     178             : 
     179             : 
     180       27655 : NTSTATUS smb2_create_blob_add(TALLOC_CTX *mem_ctx, struct smb2_create_blobs *b,
     181             :                               const char *tag, DATA_BLOB data)
     182             : {
     183           0 :         struct smb2_create_blob *array;
     184             : 
     185       27655 :         array = talloc_realloc(mem_ctx, b->blobs,
     186             :                                struct smb2_create_blob,
     187             :                                b->num_blobs + 1);
     188       27655 :         NT_STATUS_HAVE_NO_MEMORY(array);
     189       27655 :         b->blobs = array;
     190             : 
     191       27655 :         b->blobs[b->num_blobs].tag = talloc_strdup(b->blobs, tag);
     192       27655 :         NT_STATUS_HAVE_NO_MEMORY(b->blobs[b->num_blobs].tag);
     193             : 
     194       27655 :         if (data.data) {
     195       27525 :                 b->blobs[b->num_blobs].data = data_blob_talloc(b->blobs,
     196             :                                                                data.data,
     197             :                                                                data.length);
     198       27525 :                 NT_STATUS_HAVE_NO_MEMORY(b->blobs[b->num_blobs].data.data);
     199             :         } else {
     200         130 :                 b->blobs[b->num_blobs].data = data_blob_null;
     201             :         }
     202             : 
     203       27655 :         b->num_blobs += 1;
     204             : 
     205       27655 :         return NT_STATUS_OK;
     206             : }
     207             : 
     208             : /*
     209             :  * return the first blob with the given tag
     210             :  */
     211     6204601 : struct smb2_create_blob *smb2_create_blob_find(const struct smb2_create_blobs *b,
     212             :                                                const char *tag)
     213             : {
     214       12002 :         uint32_t i;
     215             : 
     216     6204601 :         if (b == NULL) {
     217       90179 :                 return NULL;
     218             :         }
     219             : 
     220     6213818 :         for (i=0; i < b->num_blobs; i++) {
     221      111758 :                 if (strcmp(b->blobs[i].tag, tag) == 0) {
     222       11172 :                         return &b->blobs[i];
     223             :                 }
     224             :         }
     225             : 
     226     6091248 :         return NULL;
     227             : }

Generated by: LCOV version 1.14