LCOV - code coverage report
Current view: top level - source4/libcli/raw - raweas.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 160 182 87.9 %
Date: 2024-04-21 15:09:00 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    parsing of EA (extended attribute) lists
       4             :    Copyright (C) Andrew Tridgell 2003
       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 "libcli/raw/libcliraw.h"
      22             : #include "libcli/raw/raw_proto.h"
      23             : 
      24             : /*
      25             :   work out how many bytes on the wire a ea list will consume.
      26             :   This assumes the names are strict ascii, which should be a
      27             :   reasonable assumption
      28             : */
      29        6745 : size_t ea_list_size(unsigned int num_eas, struct ea_struct *eas)
      30             : {
      31        6745 :         unsigned int total = 4;
      32        1022 :         int i;
      33       15635 :         for (i=0;i<num_eas;i++) {
      34        8890 :                 total += 4 + strlen(eas[i].name.s)+1 + eas[i].value.length;
      35             :         }
      36        6745 :         return total;
      37             : }
      38             : 
      39             : /*
      40             :   work out how many bytes on the wire a ea name list will consume.
      41             : */
      42         165 : static unsigned int ea_name_list_size(unsigned int num_names, struct ea_name *eas)
      43             : {
      44         165 :         unsigned int total = 4;
      45          28 :         int i;
      46         344 :         for (i=0;i<num_names;i++) {
      47         179 :                 total += 1 + strlen(eas[i].name.s) + 1;
      48             :         }
      49         165 :         return total;
      50             : }
      51             : 
      52             : /*
      53             :   work out how many bytes on the wire a chained ea list will consume.
      54             :   This assumes the names are strict ascii, which should be a
      55             :   reasonable assumption
      56             : */
      57         261 : size_t ea_list_size_chained(unsigned int num_eas, struct ea_struct *eas, unsigned alignment)
      58             : {
      59         261 :         unsigned int total = 0;
      60           3 :         int i;
      61         774 :         for (i=0;i<num_eas;i++) {
      62         513 :                 unsigned int len = 8 + strlen(eas[i].name.s)+1 + eas[i].value.length;
      63         513 :                 len = (len + (alignment-1)) & ~(alignment-1);
      64         513 :                 total += len;
      65             :         }
      66         261 :         return total;
      67             : }
      68             : 
      69             : /*
      70             :   put a ea_list into a pre-allocated buffer - buffer must be at least
      71             :   of size ea_list_size()
      72             : */
      73        3372 : void ea_put_list(uint8_t *data, unsigned int num_eas, struct ea_struct *eas)
      74             : {
      75         511 :         int i;
      76         511 :         uint32_t ea_size;
      77             : 
      78        3372 :         ea_size = ea_list_size(num_eas, eas);
      79             : 
      80        3372 :         SIVAL(data, 0, ea_size);
      81        3372 :         data += 4;
      82             : 
      83        7816 :         for (i=0;i<num_eas;i++) {
      84        4444 :                 unsigned int nlen = strlen(eas[i].name.s);
      85        4444 :                 SCVAL(data, 0, eas[i].flags);
      86        4444 :                 SCVAL(data, 1, nlen);
      87        4444 :                 SSVAL(data, 2, eas[i].value.length);
      88        4444 :                 memcpy(data+4, eas[i].name.s, nlen+1);
      89        4444 :                 if (eas[i].value.length > 0) {
      90        3949 :                         memcpy(data + 4 + nlen + 1,
      91        3380 :                                eas[i].value.data,
      92        3023 :                                eas[i].value.length);
      93             :                 }
      94        4444 :                 data += 4+nlen+1+eas[i].value.length;
      95             :         }
      96        3372 : }
      97             : 
      98             : 
      99             : /*
     100             :   put a chained ea_list into a pre-allocated buffer - buffer must be
     101             :   at least of size ea_list_size()
     102             : */
     103         259 : void ea_put_list_chained(uint8_t *data, unsigned int num_eas, struct ea_struct *eas,
     104             :                          unsigned alignment)
     105             : {
     106           3 :         int i;
     107             : 
     108         772 :         for (i=0;i<num_eas;i++) {
     109         513 :                 unsigned int nlen = strlen(eas[i].name.s);
     110         513 :                 uint32_t len = 8+nlen+1+eas[i].value.length;
     111         513 :                 unsigned int pad = ((len + (alignment-1)) & ~(alignment-1)) - len;
     112         513 :                 if (i == num_eas-1) {
     113         257 :                         SIVAL(data, 0, 0);
     114             :                 } else {
     115         256 :                         SIVAL(data, 0, len+pad);
     116             :                 }
     117         513 :                 SCVAL(data, 4, eas[i].flags);
     118         513 :                 SCVAL(data, 5, nlen);
     119         513 :                 SSVAL(data, 6, eas[i].value.length);
     120         513 :                 memcpy(data+8, eas[i].name.s, nlen+1);
     121         513 :                 memcpy(data+8+nlen+1, eas[i].value.data, eas[i].value.length);
     122         513 :                 memset(data+len, 0, pad);
     123         513 :                 data += len + pad;
     124             :         }
     125         259 : }
     126             : 
     127             : 
     128             : /*
     129             :   pull a ea_struct from a buffer. Return the number of bytes consumed
     130             : */
     131         869 : unsigned int ea_pull_struct(const DATA_BLOB *blob,
     132             :                       TALLOC_CTX *mem_ctx,
     133             :                       struct ea_struct *ea)
     134             : {
     135          28 :         uint8_t nlen;
     136          28 :         uint16_t vlen;
     137             : 
     138         869 :         ZERO_STRUCTP(ea);
     139             : 
     140         869 :         if (blob->length < 6) {
     141           0 :                 return 0;
     142             :         }
     143             : 
     144         869 :         ea->flags = CVAL(blob->data, 0);
     145         869 :         nlen = CVAL(blob->data, 1);
     146         869 :         vlen = SVAL(blob->data, 2);
     147             : 
     148         869 :         if (nlen+1+vlen > blob->length-4) {
     149           0 :                 return 0;
     150             :         }
     151             : 
     152         869 :         ea->name.s = talloc_strndup(mem_ctx, (const char *)(blob->data+4), nlen);
     153         869 :         ea->name.private_length = nlen;
     154         869 :         ea->value = data_blob_talloc(mem_ctx, NULL, vlen+1);
     155         869 :         if (!ea->value.data) return 0;
     156         869 :         if (vlen) {
     157         794 :                 memcpy(ea->value.data, blob->data+4+nlen+1, vlen);
     158             :         }
     159         869 :         ea->value.data[vlen] = 0;
     160         869 :         ea->value.length--;
     161             : 
     162         869 :         return 4 + nlen+1 + vlen;
     163             : }
     164             : 
     165             : 
     166             : /*
     167             :   pull a ea_list from a buffer
     168             : */
     169         495 : NTSTATUS ea_pull_list(const DATA_BLOB *blob,
     170             :                       TALLOC_CTX *mem_ctx,
     171             :                       unsigned int *num_eas, struct ea_struct **eas)
     172             : {
     173          28 :         int n;
     174          28 :         uint32_t ea_size, ofs;
     175             : 
     176         495 :         if (blob->length < 4) {
     177           4 :                 return NT_STATUS_INFO_LENGTH_MISMATCH;
     178             :         }
     179             : 
     180         491 :         ea_size = IVAL(blob->data, 0);
     181         491 :         if (ea_size > blob->length) {
     182           0 :                 return NT_STATUS_INVALID_PARAMETER;
     183             :         }
     184             : 
     185         491 :         ofs = 4;
     186         491 :         n = 0;
     187         491 :         *num_eas = 0;
     188         491 :         *eas = NULL;
     189             : 
     190        1318 :         while (ofs < ea_size) {
     191          28 :                 unsigned int len;
     192          28 :                 DATA_BLOB blob2;
     193             : 
     194         827 :                 blob2.data = blob->data + ofs;
     195         827 :                 blob2.length = ea_size - ofs;
     196             : 
     197         827 :                 *eas = talloc_realloc(mem_ctx, *eas, struct ea_struct, n+1);
     198         827 :                 if (! *eas) return NT_STATUS_NO_MEMORY;
     199             : 
     200         827 :                 len = ea_pull_struct(&blob2, mem_ctx, &(*eas)[n]);
     201         827 :                 if (len == 0) {
     202           0 :                         return NT_STATUS_INVALID_PARAMETER;
     203             :                 }
     204             : 
     205         827 :                 ofs += len;
     206         827 :                 n++;
     207             :         }
     208             : 
     209         491 :         *num_eas = n;
     210             : 
     211         491 :         return NT_STATUS_OK;
     212             : }
     213             : 
     214             : 
     215             : /*
     216             :   pull a chained ea_list from a buffer
     217             : */
     218          23 : NTSTATUS ea_pull_list_chained(const DATA_BLOB *blob,
     219             :                               TALLOC_CTX *mem_ctx,
     220             :                               unsigned int *num_eas, struct ea_struct **eas)
     221             : {
     222           0 :         int n;
     223           0 :         uint32_t ofs;
     224             : 
     225          23 :         if (blob->length < 4) {
     226           0 :                 return NT_STATUS_INFO_LENGTH_MISMATCH;
     227             :         }
     228             : 
     229          23 :         ofs = 0;
     230          23 :         n = 0;
     231          23 :         *num_eas = 0;
     232          23 :         *eas = NULL;
     233             : 
     234          42 :         while (ofs < blob->length) {
     235           0 :                 unsigned int len;
     236           0 :                 DATA_BLOB blob2;
     237          42 :                 uint32_t next_ofs = IVAL(blob->data, ofs);
     238             : 
     239          42 :                 blob2.data = blob->data + ofs + 4;
     240          42 :                 blob2.length = blob->length - (ofs + 4);
     241             : 
     242          42 :                 *eas = talloc_realloc(mem_ctx, *eas, struct ea_struct, n+1);
     243          42 :                 if (! *eas) return NT_STATUS_NO_MEMORY;
     244             : 
     245          42 :                 len = ea_pull_struct(&blob2, mem_ctx, &(*eas)[n]);
     246          42 :                 if (len == 0) {
     247           0 :                         return NT_STATUS_INVALID_PARAMETER;
     248             :                 }
     249             : 
     250          42 :                 if (ofs + next_ofs < ofs) {
     251           0 :                         return NT_STATUS_INVALID_PARAMETER;
     252             :                 }
     253             : 
     254          42 :                 ofs += next_ofs;
     255          42 :                 if (ofs+4 > blob->length || ofs+4 < ofs) {
     256           0 :                         return NT_STATUS_INVALID_PARAMETER;
     257             :                 }
     258          42 :                 n++;
     259          42 :                 if (next_ofs == 0) break;
     260             :         }
     261             : 
     262          23 :         *num_eas = n;
     263             : 
     264          23 :         return NT_STATUS_OK;
     265             : }
     266             : 
     267             : 
     268             : /*
     269             :   pull a ea_name from a buffer. Return the number of bytes consumed
     270             : */
     271          11 : static unsigned int ea_pull_name(const DATA_BLOB *blob,
     272             :                            TALLOC_CTX *mem_ctx,
     273             :                            struct ea_name *ea)
     274             : {
     275           0 :         uint8_t nlen;
     276             : 
     277          11 :         if (blob->length < 2) {
     278           0 :                 return 0;
     279             :         }
     280             : 
     281          11 :         nlen = CVAL(blob->data, 0);
     282             : 
     283          11 :         if (nlen+2 > blob->length) {
     284           0 :                 return 0;
     285             :         }
     286             : 
     287          11 :         ea->name.s = talloc_strndup(mem_ctx, (const char *)(blob->data+1), nlen);
     288          11 :         ea->name.private_length = nlen;
     289             : 
     290          11 :         return nlen+2;
     291             : }
     292             : 
     293             : 
     294             : /*
     295             :   pull a ea_name list from a buffer
     296             : */
     297          15 : NTSTATUS ea_pull_name_list(const DATA_BLOB *blob,
     298             :                            TALLOC_CTX *mem_ctx,
     299             :                            unsigned int *num_names, struct ea_name **ea_names)
     300             : {
     301           0 :         int n;
     302           0 :         uint32_t ea_size, ofs;
     303             : 
     304          15 :         if (blob->length < 4) {
     305           6 :                 return NT_STATUS_INFO_LENGTH_MISMATCH;
     306             :         }
     307             : 
     308           9 :         ea_size = IVAL(blob->data, 0);
     309           9 :         if (ea_size > blob->length) {
     310           0 :                 return NT_STATUS_INVALID_PARAMETER;
     311             :         }
     312             : 
     313           9 :         ofs = 4;
     314           9 :         n = 0;
     315           9 :         *num_names = 0;
     316           9 :         *ea_names = NULL;
     317             : 
     318          20 :         while (ofs < ea_size) {
     319           0 :                 unsigned int len;
     320           0 :                 DATA_BLOB blob2;
     321             : 
     322          11 :                 blob2.data = blob->data + ofs;
     323          11 :                 blob2.length = ea_size - ofs;
     324             : 
     325          11 :                 *ea_names = talloc_realloc(mem_ctx, *ea_names, struct ea_name, n+1);
     326          11 :                 if (! *ea_names) return NT_STATUS_NO_MEMORY;
     327             : 
     328          11 :                 len = ea_pull_name(&blob2, mem_ctx, &(*ea_names)[n]);
     329          11 :                 if (len == 0) {
     330           0 :                         return NT_STATUS_INVALID_PARAMETER;
     331             :                 }
     332             : 
     333          11 :                 ofs += len;
     334          11 :                 n++;
     335             :         }
     336             : 
     337           9 :         *num_names = n;
     338             : 
     339           9 :         return NT_STATUS_OK;
     340             : }
     341             : 
     342             : 
     343             : /*
     344             :   put a ea_name list into a data blob
     345             : */
     346         165 : bool ea_push_name_list(TALLOC_CTX *mem_ctx,
     347             :                        DATA_BLOB *data, unsigned int num_names, struct ea_name *eas)
     348             : {
     349          28 :         int i;
     350          28 :         uint32_t ea_size;
     351          28 :         uint32_t off;
     352             : 
     353         165 :         ea_size = ea_name_list_size(num_names, eas);
     354             : 
     355         165 :         *data = data_blob_talloc(mem_ctx, NULL, ea_size);
     356         165 :         if (data->data == NULL) {
     357           0 :                 return false;
     358             :         }
     359             : 
     360         165 :         SIVAL(data->data, 0, ea_size);
     361         165 :         off = 4;
     362             : 
     363         344 :         for (i=0;i<num_names;i++) {
     364         179 :                 unsigned int nlen = strlen(eas[i].name.s);
     365         179 :                 SCVAL(data->data, off, nlen);
     366         179 :                 memcpy(data->data+off+1, eas[i].name.s, nlen+1);
     367         179 :                 off += 1+nlen+1;
     368             :         }
     369             : 
     370         137 :         return true;
     371             : }

Generated by: LCOV version 1.14