root/source4/libcli/raw/raweas.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ea_list_size
  2. ea_name_list_size
  3. ea_list_size_chained
  4. ea_put_list
  5. ea_put_list_chained
  6. ea_pull_struct
  7. ea_pull_list
  8. ea_pull_list_chained
  9. ea_pull_name
  10. ea_pull_name_list
  11. ea_push_name_list

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

/* [<][>][^][v][top][bottom][index][help] */