LCOV - code coverage report
Current view: top level - source4/libcli/raw - raweas.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 145 158 91.8 %
Date: 2021-09-23 10:06:22 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        6741 : size_t ea_list_size(unsigned int num_eas, struct ea_struct *eas)
      30             : {
      31        6741 :         unsigned int total = 4;
      32             :         int i;
      33       15627 :         for (i=0;i<num_eas;i++) {
      34        8886 :                 total += 4 + strlen(eas[i].name.s)+1 + eas[i].value.length;
      35             :         }
      36        6741 :         return total;
      37             : }
      38             : 
      39             : /*
      40             :   work out how many bytes on the wire a ea name list will consume. 
      41             : */
      42         137 : static unsigned int ea_name_list_size(unsigned int num_names, struct ea_name *eas)
      43             : {
      44         165 :         unsigned int total = 4;
      45             :         int i;
      46         344 :         for (i=0;i<num_names;i++) {
      47         179 :                 total += 1 + strlen(eas[i].name.s) + 1;
      48             :         }
      49         137 :         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         248 : size_t ea_list_size_chained(unsigned int num_eas, struct ea_struct *eas, unsigned alignment)
      58             : {
      59         248 :         unsigned int total = 0;
      60             :         int i;
      61         747 :         for (i=0;i<num_eas;i++) {
      62         499 :                 unsigned int len = 8 + strlen(eas[i].name.s)+1 + eas[i].value.length;
      63         499 :                 len = (len + (alignment-1)) & ~(alignment-1);
      64         499 :                 total += len;
      65             :         }
      66         248 :         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        3370 : void ea_put_list(uint8_t *data, unsigned int num_eas, struct ea_struct *eas)
      74             : {
      75             :         int i;
      76             :         uint32_t ea_size;
      77             : 
      78        3370 :         ea_size = ea_list_size(num_eas, eas);
      79             : 
      80        3370 :         SIVAL(data, 0, ea_size);
      81        3370 :         data += 4;
      82             : 
      83        7812 :         for (i=0;i<num_eas;i++) {
      84        4442 :                 unsigned int nlen = strlen(eas[i].name.s);
      85        4442 :                 SCVAL(data, 0, eas[i].flags);
      86        4442 :                 SCVAL(data, 1, nlen);
      87        4442 :                 SSVAL(data, 2, eas[i].value.length);
      88        5011 :                 memcpy(data+4, eas[i].name.s, nlen+1);
      89        4442 :                 if (eas[i].value.length > 0) {
      90        6003 :                         memcpy(data + 4 + nlen + 1,
      91        3378 :                                eas[i].value.data,
      92        3021 :                                eas[i].value.length);
      93             :                 }
      94        4442 :                 data += 4+nlen+1+eas[i].value.length;
      95             :         }
      96        3370 : }
      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         248 : void ea_put_list_chained(uint8_t *data, unsigned int num_eas, struct ea_struct *eas,
     104             :                          unsigned alignment)
     105             : {
     106             :         int i;
     107             : 
     108         747 :         for (i=0;i<num_eas;i++) {
     109         499 :                 unsigned int nlen = strlen(eas[i].name.s);
     110         499 :                 uint32_t len = 8+nlen+1+eas[i].value.length;
     111         499 :                 unsigned int pad = ((len + (alignment-1)) & ~(alignment-1)) - len;
     112         499 :                 if (i == num_eas-1) {
     113         248 :                         SIVAL(data, 0, 0);
     114             :                 } else {
     115         251 :                         SIVAL(data, 0, len+pad);
     116             :                 }
     117         499 :                 SCVAL(data, 4, eas[i].flags);
     118         499 :                 SCVAL(data, 5, nlen);
     119         499 :                 SSVAL(data, 6, eas[i].value.length);
     120         506 :                 memcpy(data+8, eas[i].name.s, nlen+1);
     121         506 :                 memcpy(data+8+nlen+1, eas[i].value.data, eas[i].value.length);
     122         506 :                 memset(data+len, 0, pad);
     123         499 :                 data += len + pad;
     124             :         }
     125         248 : }
     126             : 
     127             : 
     128             : /*
     129             :   pull a ea_struct from a buffer. Return the number of bytes consumed
     130             : */
     131         847 : unsigned int ea_pull_struct(const DATA_BLOB *blob,
     132             :                       TALLOC_CTX *mem_ctx,
     133             :                       struct ea_struct *ea)
     134             : {
     135             :         uint8_t nlen;
     136             :         uint16_t vlen;
     137             : 
     138         847 :         ZERO_STRUCTP(ea);
     139             : 
     140         847 :         if (blob->length < 6) {
     141           0 :                 return 0;
     142             :         }
     143             : 
     144         847 :         ea->flags = CVAL(blob->data, 0);
     145         847 :         nlen = CVAL(blob->data, 1);
     146         847 :         vlen = SVAL(blob->data, 2);
     147             : 
     148         847 :         if (nlen+1+vlen > blob->length-4) {
     149           0 :                 return 0;
     150             :         }
     151             : 
     152         847 :         ea->name.s = talloc_strndup(mem_ctx, (const char *)(blob->data+4), nlen);
     153         847 :         ea->name.private_length = nlen;
     154         847 :         ea->value = data_blob_talloc(mem_ctx, NULL, vlen+1);
     155         847 :         if (!ea->value.data) return 0;
     156         847 :         if (vlen) {
     157         772 :                 memcpy(ea->value.data, blob->data+4+nlen+1, vlen);
     158             :         }
     159         847 :         ea->value.data[vlen] = 0;
     160         847 :         ea->value.length--;
     161             : 
     162         847 :         return 4 + nlen+1 + vlen;
     163             : }
     164             : 
     165             : 
     166             : /*
     167             :   pull a ea_list from a buffer
     168             : */
     169         493 : NTSTATUS ea_pull_list(const DATA_BLOB *blob, 
     170             :                       TALLOC_CTX *mem_ctx,
     171             :                       unsigned int *num_eas, struct ea_struct **eas)
     172             : {
     173             :         int n;
     174             :         uint32_t ea_size, ofs;
     175             : 
     176         493 :         if (blob->length < 4) {
     177           4 :                 return NT_STATUS_INFO_LENGTH_MISMATCH;
     178             :         }
     179             : 
     180         489 :         ea_size = IVAL(blob->data, 0);
     181         489 :         if (ea_size > blob->length) {
     182           0 :                 return NT_STATUS_INVALID_PARAMETER;
     183             :         }
     184             : 
     185         489 :         ofs = 4;
     186         489 :         n = 0;
     187         489 :         *num_eas = 0;
     188         489 :         *eas = NULL;
     189             : 
     190        1770 :         while (ofs < ea_size) {
     191             :                 unsigned int len;
     192             :                 DATA_BLOB blob2;
     193             : 
     194         825 :                 blob2.data = blob->data + ofs;
     195         825 :                 blob2.length = ea_size - ofs;
     196             : 
     197         825 :                 *eas = talloc_realloc(mem_ctx, *eas, struct ea_struct, n+1);
     198         825 :                 if (! *eas) return NT_STATUS_NO_MEMORY;
     199             : 
     200         825 :                 len = ea_pull_struct(&blob2, mem_ctx, &(*eas)[n]);
     201         825 :                 if (len == 0) {
     202           0 :                         return NT_STATUS_INVALID_PARAMETER;
     203             :                 }
     204             : 
     205         825 :                 ofs += len;
     206         825 :                 n++;
     207             :         }
     208             : 
     209         489 :         *num_eas = n;
     210             : 
     211         489 :         return NT_STATUS_OK;
     212             : }
     213             : 
     214             : 
     215             : /*
     216             :   pull a chained ea_list from a buffer
     217             : */
     218          12 : 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             :         int n;
     223             :         uint32_t ofs;
     224             : 
     225          12 :         if (blob->length < 4) {
     226           0 :                 return NT_STATUS_INFO_LENGTH_MISMATCH;
     227             :         }
     228             : 
     229          12 :         ofs = 0;
     230          12 :         n = 0;
     231          12 :         *num_eas = 0;
     232          12 :         *eas = NULL;
     233             : 
     234          34 :         while (ofs < blob->length) {
     235             :                 unsigned int len;
     236             :                 DATA_BLOB blob2;
     237          22 :                 uint32_t next_ofs = IVAL(blob->data, ofs);
     238             : 
     239          22 :                 blob2.data = blob->data + ofs + 4;
     240          22 :                 blob2.length = blob->length - (ofs + 4);
     241             : 
     242          22 :                 *eas = talloc_realloc(mem_ctx, *eas, struct ea_struct, n+1);
     243          22 :                 if (! *eas) return NT_STATUS_NO_MEMORY;
     244             : 
     245          22 :                 len = ea_pull_struct(&blob2, mem_ctx, &(*eas)[n]);
     246          22 :                 if (len == 0) {
     247           0 :                         return NT_STATUS_INVALID_PARAMETER;
     248             :                 }
     249             : 
     250          22 :                 if (ofs + next_ofs < ofs) {
     251           0 :                         return NT_STATUS_INVALID_PARAMETER;
     252             :                 }
     253             : 
     254          22 :                 ofs += next_ofs;
     255          22 :                 if (ofs+4 > blob->length || ofs+4 < ofs) {
     256           0 :                         return NT_STATUS_INVALID_PARAMETER;
     257             :                 }
     258          22 :                 n++;
     259          22 :                 if (next_ofs == 0) break;
     260             :         }
     261             : 
     262          12 :         *num_eas = n;
     263             : 
     264          12 :         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             :         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             :         int n;
     302             :         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          29 :         while (ofs < ea_size) {
     319             :                 unsigned int len;
     320             :                 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             :         int i;
     350             :         uint32_t ea_size;
     351             :         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         207 :                 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.13