LCOV - code coverage report
Current view: top level - libcli/smb - smb2_create_blob.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 97 107 90.7 %
Date: 2024-06-13 04:01:37 Functions: 7 7 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         278 : static size_t smb2_create_blob_padding(uint32_t offset, size_t n)
      27             : {
      28         278 :         if ((offset & (n-1)) == 0) return 0;
      29         199 :         return n - (offset & (n-1));
      30             : }
      31             : 
      32             : /*
      33             :   parse a set of SMB2 create blobs
      34             : */
      35      368235 : NTSTATUS smb2_create_blob_parse(TALLOC_CTX *mem_ctx, const DATA_BLOB buffer,
      36             :                                 struct smb2_create_blobs *blobs)
      37             : {
      38      368235 :         const uint8_t *data = buffer.data;
      39      368235 :         uint32_t remaining = buffer.length;
      40             : 
      41      733449 :         while (remaining > 0) {
      42             :                 uint32_t next;
      43             :                 uint32_t name_offset, name_length;
      44             :                 uint32_t data_offset;
      45             :                 uint32_t data_length;
      46             :                 char *tag;
      47             :                 DATA_BLOB b;
      48             :                 NTSTATUS status;
      49             : 
      50         201 :                 if (remaining < 16) {
      51           4 :                         return NT_STATUS_INVALID_PARAMETER;
      52             :                 }
      53         201 :                 next        = IVAL(data, 0);
      54         201 :                 name_offset = SVAL(data, 4);
      55         201 :                 name_length = SVAL(data, 6);
      56             : #if 0
      57             :                 reserved    = SVAL(data, 8);
      58             : #endif
      59         201 :                 data_offset = SVAL(data, 10);
      60         201 :                 data_length = IVAL(data, 12);
      61             : 
      62         201 :                 if ((next & 0x7) != 0 ||
      63         201 :                     next > remaining ||
      64         201 :                     name_offset != 16 ||
      65         197 :                     name_length < 4 ||
      66         394 :                     name_offset + name_length > remaining ||
      67         394 :                     (data_offset & 0x7) != 0 ||
      68         197 :                     (data_offset && (data_offset < name_offset + name_length)) ||
      69         197 :                     (data_offset > remaining) ||
      70         197 :                     (data_offset + (uint64_t)data_length > remaining)) {
      71           4 :                         return NT_STATUS_INVALID_PARAMETER;
      72             :                 }
      73             : 
      74         197 :                 tag = talloc_strndup(mem_ctx, (const char *)data + name_offset, name_length);
      75         197 :                 if (tag == NULL) {
      76           0 :                         return NT_STATUS_NO_MEMORY;
      77             :                 }
      78             : 
      79         197 :                 b = data_blob_const(data+data_offset, data_length);
      80         197 :                 status = smb2_create_blob_add(mem_ctx, blobs, tag, b);
      81         197 :                 if (!NT_STATUS_IS_OK(status)) {
      82           0 :                         return status;
      83             :                 }
      84             : 
      85         197 :                 talloc_free(tag);
      86             : 
      87         197 :                 if (next == 0) break;
      88             : 
      89          77 :                 remaining -= next;
      90          77 :                 data += next;
      91             : 
      92          77 :                 if (remaining < 16) {
      93           0 :                         return NT_STATUS_INVALID_PARAMETER;
      94             :                 }
      95             :         }
      96             : 
      97      368231 :         return NT_STATUS_OK;
      98             : }
      99             : 
     100             : 
     101             : /*
     102             :   add a blob to a smb2_create attribute blob
     103             : */
     104         201 : 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         201 :         uint32_t ofs = buffer->length;
     109         201 :         size_t tag_length = strlen(blob->tag);
     110         201 :         size_t blob_offset = 0;
     111         201 :         size_t blob_pad = 0;
     112         201 :         size_t next_offset = 0;
     113         201 :         size_t next_pad = 0;
     114             :         bool ok;
     115             : 
     116         201 :         blob_offset = 0x10 + tag_length;
     117         201 :         blob_pad = smb2_create_blob_padding(blob_offset, 8);
     118         201 :         next_offset = blob_offset + blob_pad + blob->data.length;
     119         201 :         if (!last) {
     120          77 :                 next_pad = smb2_create_blob_padding(next_offset, 8);
     121             :         }
     122             : 
     123         201 :         ok = data_blob_realloc(mem_ctx, buffer,
     124         201 :                                buffer->length + next_offset + next_pad);
     125         201 :         if (!ok) {
     126           0 :                 return NT_STATUS_NO_MEMORY;
     127             :         }
     128             : 
     129         201 :         if (last) {
     130         124 :                 SIVAL(buffer->data, ofs+0x00, 0);
     131             :         } else {
     132          77 :                 SIVAL(buffer->data, ofs+0x00, next_offset + next_pad);
     133             :         }
     134         201 :         SSVAL(buffer->data, ofs+0x04, 0x10); /* offset of tag */
     135         201 :         SIVAL(buffer->data, ofs+0x06, tag_length); /* tag length */
     136         201 :         SSVAL(buffer->data, ofs+0x0A, blob_offset + blob_pad); /* offset of data */
     137         201 :         SIVAL(buffer->data, ofs+0x0C, blob->data.length);
     138         201 :         memcpy(buffer->data+ofs+0x10, blob->tag, tag_length);
     139         201 :         if (blob_pad > 0) {
     140         199 :                 memset(buffer->data+ofs+blob_offset, 0, blob_pad);
     141         199 :                 blob_offset += blob_pad;
     142             :         }
     143         201 :         memcpy(buffer->data+ofs+blob_offset, blob->data.data, blob->data.length);
     144         201 :         if (next_pad > 0) {
     145           0 :                 memset(buffer->data+ofs+next_offset, 0, next_pad);
     146             :         }
     147             : 
     148         201 :         return NT_STATUS_OK;
     149             : }
     150             : 
     151             : 
     152             : /*
     153             :   create a buffer of a set of create blobs
     154             : */
     155      377747 : NTSTATUS smb2_create_blob_push(TALLOC_CTX *mem_ctx, DATA_BLOB *buffer,
     156             :                                const struct smb2_create_blobs blobs)
     157             : {
     158             :         uint32_t i;
     159             :         NTSTATUS status;
     160             : 
     161      377747 :         *buffer = (DATA_BLOB) { 0 };
     162      377948 :         for (i=0; i < blobs.num_blobs; i++) {
     163         201 :                 bool last = false;
     164             :                 const struct smb2_create_blob *c;
     165             : 
     166         201 :                 if ((i + 1) == blobs.num_blobs) {
     167         124 :                         last = true;
     168             :                 }
     169             : 
     170         201 :                 c = &blobs.blobs[i];
     171         201 :                 status = smb2_create_blob_push_one(mem_ctx, buffer, c, last);
     172         201 :                 if (!NT_STATUS_IS_OK(status)) {
     173           0 :                         return status;
     174             :                 }
     175             :         }
     176      377747 :         return NT_STATUS_OK;
     177             : }
     178             : 
     179             : 
     180         411 : NTSTATUS smb2_create_blob_add(TALLOC_CTX *mem_ctx, struct smb2_create_blobs *b,
     181             :                               const char *tag, DATA_BLOB data)
     182             : {
     183             :         struct smb2_create_blob *array;
     184             : 
     185         411 :         array = talloc_realloc(mem_ctx, b->blobs,
     186             :                                struct smb2_create_blob,
     187             :                                b->num_blobs + 1);
     188         411 :         NT_STATUS_HAVE_NO_MEMORY(array);
     189         411 :         b->blobs = array;
     190             : 
     191         411 :         b->blobs[b->num_blobs].tag = talloc_strdup(b->blobs, tag);
     192         411 :         NT_STATUS_HAVE_NO_MEMORY(b->blobs[b->num_blobs].tag);
     193             : 
     194         411 :         if (data.data) {
     195         352 :                 b->blobs[b->num_blobs].data = data_blob_talloc(b->blobs,
     196             :                                                                data.data,
     197             :                                                                data.length);
     198         352 :                 NT_STATUS_HAVE_NO_MEMORY(b->blobs[b->num_blobs].data.data);
     199             :         } else {
     200          59 :                 b->blobs[b->num_blobs].data = data_blob_null;
     201             :         }
     202             : 
     203         411 :         b->num_blobs += 1;
     204             : 
     205         411 :         return NT_STATUS_OK;
     206             : }
     207             : 
     208             : /*
     209             :  * return the first blob with the given tag
     210             :  */
     211      226880 : struct smb2_create_blob *smb2_create_blob_find(const struct smb2_create_blobs *b,
     212             :                                                const char *tag)
     213             : {
     214             :         uint32_t i;
     215             : 
     216      226880 :         if (b == NULL) {
     217          16 :                 return NULL;
     218             :         }
     219             : 
     220      227517 :         for (i=0; i < b->num_blobs; i++) {
     221         704 :                 if (strcmp(b->blobs[i].tag, tag) == 0) {
     222          51 :                         return &b->blobs[i];
     223             :                 }
     224             :         }
     225             : 
     226      226813 :         return NULL;
     227             : }
     228             : 
     229       17229 : void smb2_create_blob_remove(struct smb2_create_blobs *b, const char *tag)
     230             : {
     231       17229 :         struct smb2_create_blob *blob = smb2_create_blob_find(b, tag);
     232             : 
     233       17229 :         if (blob == NULL) {
     234       17229 :                 return;
     235             :         }
     236             : 
     237           0 :         TALLOC_FREE(blob->tag);
     238           0 :         data_blob_free(&blob->data);
     239             : 
     240           0 :         *blob = b->blobs[b->num_blobs-1];
     241           0 :         b->num_blobs -= 1;
     242             : }

Generated by: LCOV version 1.13